diff --git a/frontend/src/routes/home3/+page.svelte b/frontend/src/routes/home3/+page.svelte index 378d8f9..bc3c2e7 100644 --- a/frontend/src/routes/home3/+page.svelte +++ b/frontend/src/routes/home3/+page.svelte @@ -493,7 +493,7 @@ .joy-word .wm { right: -14px; bottom: -30px; font-size: 150px; font-weight: 400; color: rgba(79, 125, 168, 0.13); } .joy-quote { background: linear-gradient(165deg, #F9EDF1, #F1DEE6); border: 1px solid #eed6df; box-shadow: 0 10px 30px -22px rgba(150, 85, 115, 0.5); --accent: #b06a86; --rule: #b06a86; } .joy-quote .wm { left: 14px; top: -26px; font-size: 120px; color: rgba(176, 106, 134, 0.16); } - .joy-fact { background: linear-gradient(165deg, #F7EAE1, #EFDACB); border: 1px solid #ecd5c4; box-shadow: 0 10px 30px -22px rgba(150, 90, 55, 0.5); --accent: #b06a45; --rule: #b06a45; } + .joy-fact { background: linear-gradient(165deg, #F7EAE1, #EFDACB); border: 1px solid #ecd5c4; box-shadow: 0 10px 30px -22px rgba(150, 90, 55, 0.5); --accent: #9a5a38; --rule: #9a5a38; } .tag { display: flex; align-items: center; gap: 8px; } .tag .rule { width: 18px; height: 2px; border-radius: 2px; background: var(--rule); } diff --git a/frontend/src/routes/onthisday/+page.svelte b/frontend/src/routes/onthisday/+page.svelte index cc19958..8ec3399 100644 --- a/frontend/src/routes/onthisday/+page.svelte +++ b/frontend/src/routes/onthisday/+page.svelte @@ -24,6 +24,8 @@ let heroFit = $derived.by(() => { const url = f?.image_url || ''; if (/\.(png|svg)(\?|#|$)/i.test(url)) return 'contain'; + // filename hints catch JPEG logos/maps/crests the aspect check would crop + if (/(seal|flag|logo|map|diagram|crest|emblem|coat[_-]?of[_-]?arms)/i.test(url)) return 'contain'; if (heroAspect == null) return 'cover'; return (heroAspect < 0.9 || heroAspect > 2.0) ? 'contain' : 'cover'; }); @@ -67,18 +69,18 @@ {dateline(f.date)} -
{f.text}
{#if f.summary}{f.summary}
{/if} @@ -117,23 +119,26 @@ padding: clamp(26px, 5vw, 34px) clamp(20px, 5vw, 34px) clamp(34px, 6vw, 44px); overflow: hidden; } - /* eyebrow matches the homepage "On this day" card accent (clay/brorange) so the card → page read as one */ + /* eyebrow matches the homepage "On this day" card accent (clay) so the card → page read as one */ .eyebrow { display: flex; align-items: center; gap: 14px; } - .eye-rule { width: 34px; height: 3px; background: #b06a45; border-radius: 2px; flex: none; } - .eye-label { font-family: 'Hanken Grotesk', sans-serif; font-size: clamp(17px, 2.4vw, 22px); font-weight: 700; letter-spacing: 0.13em; text-transform: uppercase; color: #b06a45; } + .eye-rule { width: 34px; height: 3px; background: #9a5a38; border-radius: 2px; flex: none; } + .eye-label { font-family: 'Hanken Grotesk', sans-serif; font-size: clamp(17px, 2.4vw, 22px); font-weight: 700; letter-spacing: 0.13em; text-transform: uppercase; color: #9a5a38; } /* extra breathing room between the title and the content below */ .dateline { display: flex; align-items: baseline; flex-wrap: wrap; gap: 10px 16px; margin: clamp(32px, 5vw, 48px) 0 16px; } - .dl-rule { flex: 1 1 30px; min-width: 24px; height: 1.5px; align-self: flex-end; margin-bottom: 0.7em; background: rgba(70, 120, 90, 0.26); } + .dl-rule { flex: 1 1 30px; min-width: 24px; height: 1.5px; align-self: baseline; margin: 0; background: rgba(70, 120, 90, 0.26); } .dl-label { font-family: 'Hanken Grotesk', sans-serif; font-weight: 700; font-size: clamp(14px, 1.7vw, 17px); letter-spacing: 0.1em; text-transform: uppercase; color: #2c5d44; } - /* year lives here (off the image) — "IN HISTORY" top-aligned beside a big "2013", sharing - ONE baseline with the date so "2013" sits ON the line (not below it). Both green, so the - line ties in the green Read-more button. The label is raised post-layout via position: - relative, which does NOT move the baseline the date aligns to. */ - .year-block { --ys: clamp(34px, 5.5vw, 46px); display: inline-flex; align-items: baseline; gap: 7px; flex: none; } - .yb-label { position: relative; top: calc(11px - 0.7 * var(--ys)); font-family: 'Hanken Grotesk', sans-serif; font-size: 12px; font-weight: 700; letter-spacing: 0.16em; text-transform: uppercase; color: #3a7d5b; } - .yb-year { position: relative; top: -2px; font-family: 'Playfair Display', Georgia, serif; font-weight: 700; font-size: var(--ys); line-height: 1; color: #2c5d44; } + /* "2013" is the SOLE in-flow baseline anchor (shares one baseline with the date + rule); + "IN HISTORY" is absolutely positioned in the reserved start-padding so raising it can never + drag that baseline (Codex's structure). Both green so the line ties in the Read-more button. */ + .year-block { --ys: clamp(34px, 5.5vw, 46px); position: relative; display: inline-block; padding-inline-start: 90px; line-height: 1; flex: none; } + .yb-label { position: absolute; inset-inline-start: 0; top: clamp(4px, 0.7vw, 6px); line-height: 1; font-family: 'Hanken Grotesk', sans-serif; font-size: 12px; font-weight: 700; letter-spacing: 0.16em; text-transform: uppercase; color: #367653; } + .yb-year { position: static; display: inline-block; font-family: 'Playfair Display', Georgia, serif; font-weight: 700; font-size: var(--ys); line-height: 1; color: #2c5d44; } + + /* the full line can't fit cleanly on a narrow phone — wrap it deliberately: year lockup on its + own row, rule + date on the next (instead of accidental mid-line flex wrapping) */ + @media (max-width: 520px) { .year-block { flex: 0 0 100%; } } .hero { position: relative; border-radius: 12px; overflow: hidden; background: #21392e; @@ -159,14 +164,14 @@ } .cta-row { margin-top: clamp(24px, 4vw, 30px); } - /* clay to match the "On This Day" title — gives this card its own identity */ + /* clay to match the "On This Day" title — gives this card its own identity (AA: white on #9a5a38) */ .cta { - display: inline-flex; align-items: center; gap: 8px; background: #b06a45; color: #fff; + display: inline-flex; align-items: center; gap: 8px; background: #9a5a38; color: #fff; text-decoration: none; font-family: 'Hanken Grotesk', sans-serif; font-size: 14px; font-weight: 600; padding: 11px 20px; border-radius: 999px; -webkit-tap-highlight-color: transparent; transition: background 0.15s ease; } - .cta:hover { background: #9a5a38; } + .cta:hover { background: #854c2f; } .note { text-align: center; color: var(--muted); font-size: 1.05rem; margin-top: 60px; } diff --git a/frontend/src/routes/quote/+page.svelte b/frontend/src/routes/quote/+page.svelte index eb9cdd1..d8e4145 100644 --- a/frontend/src/routes/quote/+page.svelte +++ b/frontend/src/routes/quote/+page.svelte @@ -13,11 +13,13 @@ return MONTHS[m - 1] ? { mon: MONTHS[m - 1], day: d } : null; }); + // one attributed string for both Copy and Share, so native sharing keeps the author too + let attributed = $derived(q ? `“${q.text}”${q.author ? ` — ${q.author}${q.work ? ', ' + q.work : ''}` : ''}` : ''); + let copied = $state(false); async function copyQuote() { - const attr = q?.author ? ` — ${q.author}${q.work ? ', ' + q.work : ''}` : ''; try { - await navigator.clipboard.writeText(`“${q.text}”${attr}`); + await navigator.clipboard.writeText(attributed); copied = true; setTimeout(() => (copied = false), 1800); } catch { /* no clipboard — silent */ } } @@ -26,7 +28,7 @@ async function share() { const url = location.href; try { - if (navigator.share) { await navigator.share({ title: 'Quote of the Day · upbeatBytes', text: `“${q.text}”`, url }); return; } + if (navigator.share) { await navigator.share({ title: 'Quote of the Day · upbeatBytes', text: attributed, url }); return; } await navigator.clipboard.writeText(url); shared = true; setTimeout(() => (shared = false), 1800); } catch { /* cancelled / unsupported */ } @@ -150,7 +152,7 @@ .attrib { position: relative; display: flex; align-items: center; gap: 14px; margin-top: clamp(20px, 3vw, 26px); } .at-rule { width: 28px; height: 1.5px; background: #c79bac; flex: none; } - .at-by { font-family: 'Newsreader', Georgia, serif; font-size: clamp(1rem, 1.6vw, 1.13rem); color: #8f5e72; } + .at-by { font-family: 'Newsreader', Georgia, serif; font-size: clamp(1rem, 1.6vw, 1.13rem); color: #8b596d; } .work { font-style: italic; } .hr { position: relative; height: 1px; background: rgba(120, 90, 40, 0.16); margin: clamp(28px, 4vw, 38px) 0 24px; } @@ -168,10 +170,19 @@ font-size: 14px; font-weight: 600; padding: 10px 18px; border-radius: 999px; cursor: pointer; -webkit-tap-highlight-color: transparent; transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease; } - .act-copy { background: #a4607a; color: #fff; border: none; } - .act-copy:hover { background: #8f5165; } - .act-share { background: transparent; color: #8f5e72; border: 1px solid #d3b3c0; } - .act-share:hover { border-color: #a4607a; color: #a4607a; } + /* AA contrast: white on #8b596d passes; rose text uses the accessible secondary */ + .act-copy { background: #8b596d; color: #fff; border: none; } + .act-copy:hover { background: #774a5c; } + .act-share { background: transparent; color: #8b596d; border: 1px solid #d3b3c0; } + .act-share:hover { border-color: #8b596d; color: #774a5c; } .note { text-align: center; color: var(--muted); font-size: 1.05rem; margin-top: 60px; } + + /* narrow phones: keep "QUOTE OF THE DAY" + its eyelash from crowding/clipping */ + @media (max-width: 380px) { + .deckle { padding-left: clamp(18px, 6vw, 24px); padding-right: clamp(18px, 6vw, 24px); } + .eyebrow { gap: 9px; } + .eye-rule { width: 24px; } + .eye-label { letter-spacing: 0.08em; } + }