/* =============================================================================
   Xmas wishlist — design system "The Night Express"
   File: public/assets/app.css    Rewritten: 2026-11-01 (Ryan: "doesn't look like a high-end designer made it")

   CONCEPT   A night train to Christmas. Wish lists are boarding passes and tickets with real cut-out
             notches (CSS masks); headlines are brass-foil display italics; everything else is quiet.
   TOKENS    night #0B1B2B  spruce #123C34  brass #C9A24B  stock #F2E8D0 (ticket paper)
             cranberry #9E1F32  frost #CFE3EA.  One radius scale (6 / 14 / pill), one shadow recipe.
   TYPE      display: Bodoni/Didot-family serif italic (system fonts; CSP is font-src 'self' and no font files are
             bundled yet); body: system humanist sans. Sentence-case labels, no all-caps eyebrows.
   RULES     Ryan's: CSS is for light and atmosphere only, no hand-drawn objects. Characters are emoji stand-ins
             or his own images in public/assets/art. Inline style="" is blocked by the CSP: colours arrive via
             data-* attributes and app.js. Motion is limited to the gift moment and the snow; reduced motion is honoured.
   ============================================================================= */
:root{
  --night:#0B1B2B;--spruce:#123C34;--brass:#C9A24B;--brass-hi:#F2D88C;--stock:#F2E8D0;--stock-edge:#D9CBA8;
  --cranberry:#9E1F32;--frost:#CFE3EA;--ink:#1D1A16;--ink-soft:#5B5346;
  --r-s:6px;--r-m:14px;--r-pill:999px;
  --display:"Bodoni 72","Bodoni MT",Didot,"Playfair Display","Iowan Old Style","Palatino Linotype",Georgia,serif;
  --sans:"Avenir Next","Segoe UI",system-ui,-apple-system,Roboto,sans-serif;
  --shadow:0 14px 30px rgba(0,0,0,.35);
  --gutter:clamp(16px,4vw,32px);
}
*{box-sizing:border-box}
html{color-scheme:dark}
body{margin:0;font:17px/1.55 var(--sans);color:var(--frost);min-height:100vh;
 background:radial-gradient(90% 60% at 85% -10%,rgba(201,162,75,.16),transparent 60%),radial-gradient(120% 80% at 10% 0,#16463c 0,var(--spruce) 35%,var(--night) 100%) fixed;
 -webkit-font-smoothing:antialiased}
a{color:var(--brass-hi);text-underline-offset:3px}
h1,h2,h3{font-family:var(--display);font-weight:500;line-height:1.1;letter-spacing:-.01em;margin:0 0 .5em}
h1{font-size:clamp(2.2rem,6vw,3.6rem);font-style:italic}
h2{font-size:1.6rem}
h3{font-size:1.25rem}
p{margin:.4em 0 .8em}
.note{color:rgba(207,227,234,.7);font-size:.95rem}
.center{text-align:center}
.foil{background:linear-gradient(100deg,#9C7A2E 0%,var(--brass-hi) 30%,#B8923D 52%,var(--brass-hi) 74%,#9C7A2E 100%);-webkit-background-clip:text;background-clip:text;color:transparent;-webkit-text-fill-color:transparent}
main{max-width:1040px;margin:0 auto;padding:0 var(--gutter) 3rem;position:relative;z-index:1}

/* ---- header ---- */
.top{position:sticky;top:0;z-index:20;background:rgba(11,27,43,.82);backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);border-bottom:1px solid rgba(201,162,75,.28)}
.lights{height:3px;background:linear-gradient(90deg,#d9534f,var(--brass),#58b368,#4aa3c9,#c471b5,#d9534f);background-size:260px 100%;opacity:.9}
.top-in{max-width:1040px;margin:0 auto;padding:.7rem var(--gutter);display:flex;flex-wrap:wrap;align-items:center;gap:.4rem 1.4rem}
.brand{display:flex;align-items:center;gap:.5rem;font-family:var(--display);font-style:italic;font-size:1.35rem;color:var(--stock);text-decoration:none;margin-right:auto}
nav{display:flex;align-items:center;gap:.3rem}
nav a,nav button.link{color:var(--frost);text-decoration:none;padding:.35rem .7rem;border-radius:var(--r-pill);font-size:.95rem}
nav a:hover,nav button.link:hover{background:rgba(255,255,255,.08)}
.inline{display:inline}
.tools{display:flex;align-items:center;gap:.4rem}
.tool{display:inline-flex;align-items:center;gap:.4rem;background:rgba(255,255,255,.06);color:var(--frost);border:1px solid rgba(255,255,255,.14);border-radius:var(--r-pill);padding:.3rem .75rem;font-size:.85rem;box-shadow:none;text-decoration:none;min-height:34px}
.tool:hover{background:rgba(255,255,255,.12)}
.tool[aria-pressed="true"]{border-color:var(--brass);color:var(--brass-hi)}

/* ---- controls ---- */
button{font:inherit;cursor:pointer}
button.link{background:none;border:0;color:var(--brass-hi);padding:0;text-decoration:underline;text-underline-offset:3px;box-shadow:none}
button.danger,.danger{color:#ff9d9d}
button,.btn{background:var(--cranberry);color:#fff;border:1px solid rgba(255,255,255,.18);border-radius:var(--r-s);padding:.55rem 1rem;min-height:42px;font-weight:600;box-shadow:0 2px 0 rgba(0,0,0,.25)}
button:hover{filter:brightness(1.1)}
button.big{min-height:52px;padding:.75rem 1.5rem;font-size:1.08rem;border-radius:var(--r-m);background:linear-gradient(#b32a3f,#8c1a2b)}
button.wrap{background:linear-gradient(#E4C066,#B8923D);color:#2a1f05;border-color:rgba(0,0,0,.2)}
:focus-visible{outline:3px solid var(--brass-hi);outline-offset:2px;border-radius:var(--r-s)}
input,select,textarea{font:inherit;color:var(--ink);background:#fffdf7;border:1px solid var(--stock-edge);border-radius:var(--r-s);padding:.6rem .7rem;min-height:44px;max-width:100%}
textarea{width:100%;min-height:110px}
label{display:flex;flex-direction:column;gap:.3rem;font-size:.9rem;color:var(--ink-soft);font-weight:600}
.wide{width:100%}
.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:.9rem;align-items:end}
.flash{margin:1rem 0;padding:.7rem 1rem;border-radius:var(--r-m);background:rgba(201,162,75,.16);border:1px solid var(--brass);color:var(--brass-hi);font-weight:600}

/* ---- the ticket: a stock-paper card with semicircle cut-outs on both edges ---- */
.ticket{position:relative;color:var(--ink);background:var(--stock);border-radius:var(--r-s);
 -webkit-mask:radial-gradient(circle 10px at 0 var(--notch,50%),#0000 97%,#000) left/51% 100% no-repeat,radial-gradient(circle 10px at 100% var(--notch,50%),#0000 97%,#000) right/51% 100% no-repeat;
 mask:radial-gradient(circle 10px at 0 var(--notch,50%),#0000 97%,#000) left/51% 100% no-repeat,radial-gradient(circle 10px at 100% var(--notch,50%),#0000 97%,#000) right/51% 100% no-repeat}
.lift{filter:drop-shadow(0 12px 18px rgba(0,0,0,.32))}
.card{background:var(--stock);color:var(--ink);border-radius:var(--r-m);padding:1.3rem 1.5rem;margin:1.2rem 0;box-shadow:var(--shadow)}
.card h2{color:#3b2a10}
.card a{color:var(--cranberry)}
.hero.card{text-align:center;padding:2.2rem 1.5rem}

/* ---- home: departure hero ---- */
.depart{display:grid;grid-template-columns:minmax(0,1fr);gap:clamp(1.2rem,4vw,3rem);align-items:center;padding:clamp(1.6rem,5vw,3.2rem) 0 1.4rem}
.depart h1{margin-bottom:.2em}
.depart .sub{max-width:30rem;color:rgba(207,227,234,.82)}
.cd-big{display:flex;gap:clamp(.8rem,3vw,1.6rem);margin:1.2rem 0 .4rem}
.cd-big .unit{display:flex;flex-direction:column;min-width:3.2ch}
.cd-big b{font-family:var(--display);font-weight:500;font-size:clamp(2.4rem,7vw,4rem);line-height:1;font-variant-numeric:tabular-nums;color:var(--brass-hi)}
.cd-big small{font-size:.8rem;color:rgba(207,227,234,.65);margin-top:.2rem}
.cd-big.is-done b{color:var(--cranberry)}
.due-line{margin-top:.8rem;font-size:.95rem;color:rgba(207,227,234,.75)}
.due-line .cd-time{color:var(--brass-hi);font-weight:600;font-variant-numeric:tabular-nums}
.frieze{display:grid;grid-template-columns:repeat(4,1fr);gap:.7rem}
.frieze>*{display:grid;place-items:center;aspect-ratio:1;border-radius:var(--r-m);background:rgba(255,255,255,.05);border:1px solid rgba(201,162,75,.25);font-size:2.6rem;line-height:1;overflow:hidden}
.frieze img.art{width:100%;height:100%;padding:0;border-radius:0;box-shadow:none;object-fit:cover;background:#fff}
.frieze .art-emoji{filter:drop-shadow(0 4px 6px rgba(0,0,0,.4))}
.quote{max-width:38rem;margin:.6rem 0 2rem;font-family:var(--display);font-style:italic;font-size:1.25rem;line-height:1.4;color:var(--stock);border-left:2px solid var(--brass);padding-left:1rem}
.quote cite{display:block;font-family:var(--sans);font-size:.82rem;font-style:normal;color:rgba(207,227,234,.65);margin-top:.3rem}
.carol-row{margin:.2rem 0 1rem}
.section-title{display:flex;align-items:baseline;justify-content:space-between;gap:1rem;margin:1.6rem 0 .8rem}
.section-title h2{margin:0;color:var(--stock)}

/* ---- boarding passes (people) ---- */
.passes{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:1rem}
.pass{display:flex;text-decoration:none;color:var(--ink)}
.pass .ticket{display:flex;width:100%;--notch:50%}
.pass .stub{flex:0 0 78px;display:grid;place-items:center;background:var(--tag,var(--cranberry));color:#fff;font-family:var(--display);font-style:italic;font-size:2.2rem;border-right:2px dashed rgba(0,0,0,.28)}
.pass .body{padding:.9rem 1.1rem;display:flex;flex-direction:column;justify-content:center;gap:.1rem}
.pass strong{font-family:var(--display);font-size:1.5rem;font-weight:500}
.pass span{color:var(--ink-soft);font-size:.92rem}
.pass:hover .lift,.pass:focus-visible .lift{transform:translateY(-3px)}
.lift{transition:transform .18s ease}

/* ---- wish list ---- */
.page-head{padding:2rem 0 .6rem}
.page-head h1{margin-bottom:.15em}
.cd-bar{display:flex;flex-wrap:wrap;gap:.4rem 1.4rem;font-size:.92rem;color:rgba(207,227,234,.8);margin-bottom:.4rem}
.cd-bar .cd-time{color:var(--brass-hi);font-weight:600;font-variant-numeric:tabular-nums}
.items{list-style:none;padding:0;margin:1rem 0}
.items>li{margin:.8rem 0}
.item{display:flex;align-items:stretch;gap:0;--notch:50%}
.item .stub{flex:0 0 74px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.2rem;border-right:2px dashed rgba(0,0,0,.22);background:rgba(158,31,50,.06);color:#9a7a2e;font-size:.9rem;letter-spacing:.1em}
.item .stub small{font-size:.65rem;letter-spacing:0;color:var(--ink-soft)}
.item-main{flex:1;padding:.9rem 1.1rem;min-width:0}
.item-main h3{margin:0 0 .2rem;color:#2b2015}
.item-main p{margin:.15rem 0;color:var(--ink-soft)}
.item .meta{display:flex;flex-wrap:wrap;gap:.3rem 1rem;font-weight:600;color:var(--ink)}
.item .meta a{color:var(--cranberry)}
.item-side{display:flex;flex-direction:column;align-items:flex-end;justify-content:center;gap:.4rem;padding:.9rem 1.1rem;border-left:2px dashed rgba(0,0,0,.22);min-width:190px}
.item-side input{width:100%;min-height:38px;padding:.35rem .55rem;font-size:.9rem}
.item-side form{display:flex;flex-direction:column;gap:.4rem;align-items:stretch;width:100%}
.item-side .link{color:var(--cranberry)}
.gift{font-weight:700;color:#2a6b3a}
.gift small{font-weight:500;color:var(--ink-soft)}
.dup{color:#8a5200;font-size:.85rem}
.item.bought .stub{background:rgba(42,107,58,.14);color:#2a6b3a}
.item.bought .item-main h3{text-decoration:line-through;text-decoration-color:rgba(42,107,58,.55)}
.stars{color:#B8923D;letter-spacing:.12em}
.empty{padding:1.4rem 1.2rem;color:var(--ink-soft);background:var(--stock);border-radius:var(--r-m)}

/* ---- ledger ---- */
.prog{display:grid;gap:.35rem;padding:.9rem 0;border-bottom:1px dashed var(--stock-edge)}
.prog:last-child{border:0}
.prog strong{font-family:var(--display);font-size:1.3rem;font-weight:500;color:var(--tag,#3b2a10)}
.cane{height:10px;border-radius:var(--r-pill);background:#e5d8b8;overflow:hidden}
.cane i{display:block;height:100%;background:repeating-linear-gradient(45deg,#b32a3f 0 9px,#fff 9px 18px)}
.rail{position:relative;height:30px;border-bottom:3px dashed rgba(0,0,0,.28)}
.rail .ride{position:absolute;bottom:2px}
.rail .stop{position:absolute;right:0;bottom:2px;font-size:1.3rem}
.logo-wrap{text-align:center;margin:.4rem 0 1rem}

/* ---- admin / misc ---- */
.row{padding:.7rem 0;border-bottom:1px dashed var(--stock-edge);display:flex;flex-wrap:wrap;gap:.6rem 1rem;align-items:center}
.row:last-child{border:0}
.credits{list-style:none;padding:0}.credits li{padding:.4rem 0;border-bottom:1px dashed var(--stock-edge)}
.ticket-line{font-family:var(--display);font-style:italic;font-size:1.2rem;color:#7a1a22}
footer{text-align:center;color:rgba(207,227,234,.55);padding:2.5rem var(--gutter);font-size:.9rem}
footer a{color:inherit}

/* ---- art (supplied images / emoji stand-ins) ---- */
img.art{background:#fff;border-radius:var(--r-s);padding:3px;object-fit:contain}
img.art.logo{width:min(300px,80vw);height:auto;max-height:200px;box-shadow:var(--shadow);border-radius:var(--r-m)}
.art.mini{width:26px;height:26px;vertical-align:middle}.art-emoji.mini{font-size:1.4rem}
.grumpy-only{display:none}.grumpy .grumpy-only{display:inline-block}

/* ---- snow (atmosphere): two sparse layers ---- */
.snow{position:fixed;inset:0;pointer-events:none;z-index:0;background-repeat:repeat}
.s1{background-image:radial-gradient(2.5px 2.5px at 20px 30px,#fff,transparent),radial-gradient(2px 2px at 90px 120px,#fff,transparent),radial-gradient(2.5px 2.5px at 160px 60px,#fff,transparent);background-size:240px 240px;opacity:.45;animation:fall 18s linear infinite}
.s2{background-image:radial-gradient(1.8px 1.8px at 40px 70px,#fff,transparent),radial-gradient(1.8px 1.8px at 130px 20px,#fff,transparent),radial-gradient(1.4px 1.4px at 70px 150px,#fff,transparent);background-size:170px 170px;opacity:.3;animation:fall 28s linear infinite}
@keyframes fall{to{background-position:60px 240px}}
.blizzard .snow{opacity:.95;animation-duration:2.4s}

/* ---- music player pill (Stop is always one tap away) ---- */
.player{position:fixed;left:50%;bottom:1.2rem;transform:translateX(-50%);z-index:70;display:flex;align-items:center;gap:.7rem;background:var(--night);border:1px solid var(--brass);border-radius:var(--r-pill);padding:.4rem .5rem .4rem 1rem;box-shadow:var(--shadow);color:var(--stock)}
.player[hidden]{display:none}
.player-note{color:var(--brass-hi)}
.player-stop{background:var(--cranberry);min-height:34px;padding:.2rem .9rem;border-radius:var(--r-pill)}
.toast{position:fixed;left:50%;bottom:4.5rem;transform:translateX(-50%);z-index:60;max-width:min(92vw,34rem);background:var(--stock);color:var(--ink);border:1px solid var(--brass);border-radius:var(--r-m);padding:.8rem 1.1rem;box-shadow:var(--shadow);font-family:var(--display);font-style:italic;font-size:1.05rem;text-align:center}

/* ---- the gift moment (identical for every successful buy, so it reveals nothing) ---- */
.gift-pop{position:fixed;z-index:50;left:50%;top:40%;font-size:7rem;transform:translate(-50%,-50%);pointer-events:none;animation:giftpop 1.6s ease-out forwards;filter:drop-shadow(0 12px 18px rgba(0,0,0,.5))}
@keyframes giftpop{0%{transform:translate(-50%,-30%) scale(.2) rotate(-25deg);opacity:0}25%{transform:translate(-50%,-50%) scale(1.25) rotate(8deg);opacity:1}70%{transform:translate(-50%,-50%) scale(1) rotate(0);opacity:1}100%{transform:translate(-50%,-90%) scale(1.1);opacity:0}}
.confetto{position:fixed;z-index:49;top:-12px;width:9px;height:14px;border-radius:2px;pointer-events:none;animation:confall 3s linear forwards}
@keyframes confall{to{transform:translate(var(--dx),105vh) rotate(720deg)}}

/* grumpy mode: same page, sour green mood */
.grumpy body{background:radial-gradient(120% 80% at 50% 0,#3a5a1c 0,#25400f 45%,#162606 100%) fixed}
.grumpy{--brass:#b6e03a;--brass-hi:#d8ff7a;--cranberry:#4d7a12}
.grumpy .ticket{filter:hue-rotate(40deg) saturate(.85)}

/* ---- small screens: stack the hero, tickets lose their side panel ---- */
@media (max-width:780px){
  .depart{grid-template-columns:1fr}
  .frieze{grid-template-columns:repeat(4,1fr);order:2}
  .item{flex-direction:column}
  .item .stub{flex-direction:row;flex-basis:auto;padding:.4rem .9rem;border-right:0;border-bottom:2px dashed rgba(0,0,0,.22);justify-content:flex-start}
  .item-side{border-left:0;border-top:2px dashed rgba(0,0,0,.22);align-items:stretch;min-width:0}
  .top-in{gap:.4rem .8rem}.brand{flex-basis:100%}
  .item{-webkit-mask:none;mask:none}
}
@media (max-width:560px){
  /* icon-only tools: labels stay in the DOM for screen readers (clipped, not display:none) */
  .tool-label{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
  .tool{padding:.3rem .65rem}
  nav{flex-wrap:wrap;gap:.1rem}nav a,nav button.link{padding:.3rem .55rem;font-size:.9rem;white-space:nowrap}
  .cd-big{gap:.9rem}
}
@media (prefers-reduced-motion:reduce){.snow,.gift-pop,.confetto,.lift{animation:none;transition:none}.confetto{display:none}.gift-pop{opacity:1;transform:translate(-50%,-50%)}}
