:root{
  --ground:#EFE4CE;
  --ground-raised:#E4D5B8;
  --panel:#F7F1E2;
  /* Darkened from the original #9C6B1F — at that value, --ground-on-accent
     text (button.action, .welcome-cta, the active .mode-btn) measured
     3.67:1, under WCAG AA's 4.5:1 floor for normal-size text. This value
     clears 4.5:1 against --ground (and improves accent-as-link-text
     against --panel too) while staying the same warm gold/bronze hue —
     dark mode's --accent below was already compliant and is untouched.
     See docs/accessibility.md (if present) or the contrast check in this
     repo's accessibility pass for the numbers. */
  --accent:#845A1A;
  --accent-dim:#C9A463;
  --ink:#241D14;
  --ink-muted:#6B5D47;
  --card-back-a:#2C2316;
  --card-back-b:#443720;
  --shadow: 0 10px 24px rgba(36,29,20,.18);
  /* Status text colors (error/ok), used wherever a message needs to read
     as "something went wrong"/"that worked" beyond its own wording (geocode
     lookup, admin save, auth form, block/inactive badges). Previously
     hardcoded hex baked into each rule, which is how they drifted out of
     AA compliance in dark mode without anyone noticing — centralizing them
     here means one pair of values to check, and they now vary by theme
     like every other color in this file. Both checked against BOTH
     --ground and --panel at >=4.5:1 (normal-text AA). */
  --status-error:#9B3523;
  --status-ok:#3F6B3F;
}
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
    --ground:#161310; --ground-raised:#211C17; --panel:#1C1712;
    --accent:#D4A24E; --accent-dim:#8B6B35;
    --ink:#EFE6D8; --ink-muted:#B3A58E;
    --card-back-a:#120F0A; --card-back-b:#241D12;
    --shadow: 0 14px 30px rgba(0,0,0,.45);
    --status-error:#E08A74; --status-ok:#6FA86F;
  }
}
:root[data-theme="dark"]{
  --ground:#161310; --ground-raised:#211C17; --panel:#1C1712;
  --accent:#D4A24E; --accent-dim:#8B6B35;
  --ink:#EFE6D8; --ink-muted:#B3A58E;
  --card-back-a:#120F0A; --card-back-b:#241D12;
  --shadow: 0 14px 30px rgba(0,0,0,.45);
  --status-error:#E08A74; --status-ok:#6FA86F;
}

*{box-sizing:border-box;}
html,body{margin:0;padding:0;}
body{
  background:var(--ground);
  color:var(--ink);
  font-family:"Work Sans",system-ui,sans-serif;
  min-height:100vh;
  display:flex;
  flex-direction:column;
  align-items:center;
  padding:18px 20px 32px;
}
h1,h2{font-family:"Fraunces",Georgia,serif; text-wrap:balance; margin:0;}
/* Baseline for any <a> with no more specific rule — without this, a link
   falls through to the browser's own default (blue, visited purple),
   which is both off-brand and often unreadably low-contrast against this
   theme's dark-mode background. Deliberately low specificity (bare
   element selector, specificity 0-0-1) so every existing more-specific
   rule (.action, .welcome-cta, .legal-footer a, nav links, etc. — all
   0-1-0 or higher) keeps overriding it exactly as before. Author-origin
   styles already beat the browser's own user-agent :visited default
   regardless of specificity (origin is compared before specificity in
   the cascade), so this single rule covers both visited and unvisited
   states on its own — do NOT add a matching `a:visited{...}` rule here:
   :visited is a pseudo-CLASS, so `a:visited` carries specificity 0-1-1,
   which beats every single-class component rule above (0-1-0) once a
   link has been clicked once. That regression is exactly what made
   .welcome-cta's own white-on-gold text get overridden back to
   gold-on-gold (unreadable) for a visited Google sign-in link — a bug
   this comment exists to stop someone (including a future me) from
   reintroducing by "symmetry". */
a{ color:var(--accent); }

/* Visually-hidden but screen-reader-accessible text — for context a
   sighted user gets from layout/color alone (e.g. "(active)" next to a
   highlighted pill) and for the skip-link below, which only needs to be
   visible once it's focused. */
.sr-only{
  position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border:0;
}
.skip-link{
  /* inset-inline-start (not left) so this lands at the reading-start edge
     in both directions — i18n.js sets dir="rtl" for Hebrew, where "start"
     is the right edge, not the left. */
  position:absolute; inset-inline-start:8px; top:-100px; z-index:1000;
  background:var(--panel); color:var(--ink); border:1px solid var(--ink);
  padding:10px 16px; border-radius:8px; font-size:13px; font-weight:600;
  text-decoration:none; transition:top .15s ease;
}
.skip-link:focus{ top:8px; }

/* The card itself is the point of the page, so it should claim most of the
   viewport height automatically — everything else (title above, the one
   row of deck controls below, Shuffle/profile link at the very bottom) is
   kept deliberately light so it doesn't compete for space. --stage-max
   bounds the card's box by BOTH available width and available height
   (unlike a plain max-width, which only reacts to a narrower window) —
   on a short/wide window it shrinks to fit height; on a tall/narrow one
   (mobile portrait) it's bounded by width instead. */
:root{ --stage-max: min(92vw, calc(72vh * 5 / 7), 680px); }

/* Row, not column: brand (logo+title+language picker, all inline — see
   .brand below) sits on the left, account status/nav/etc. (see
   .topbar-actions) on the right, wrapping onto a second line only once
   there's truly no room for both on one — this is what keeps the page
   header to one or two compact rows on a phone instead of three separate
   centered rows (title / language / account) stacked on top of each
   other. */
.topbar{
  width:100%; max-width:1180px;
  display:flex; flex-direction:row; flex-wrap:wrap; align-items:center; justify-content:space-between;
  gap:8px 18px; margin-bottom:14px;
}
.brand{ display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
.topbar-actions{ display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
/* Capped well below the old 36px ceiling — at that size + the language
   picker now sitting inline right after it (see .brand below), the title
   alone could crowd out .topbar-actions on desktop and push the
   account-status badge onto its own second line on mobile. This still
   scales a little with viewport width (2.2vw) but tops out much sooner. */
.brand h1{ font-size:clamp(17px,2.2vw,24px); font-weight:600; font-style:italic; letter-spacing:.2px; }
/* theme-adaptive via CSS mask (same technique as .card-back-owl below) —
   dark mark in light mode, light mark in dark mode, rather than a fixed
   raster color that would vanish against a dark background. */
.brand-logo{
  display:block; width:34px; height:34px; flex:none;
  background-color:var(--ink);
  -webkit-mask-image:url(/owl-logo.png); mask-image:url(/owl-logo.png);
  -webkit-mask-size:contain; mask-size:contain;
  -webkit-mask-repeat:no-repeat; mask-repeat:no-repeat;
  -webkit-mask-position:center; mask-position:center;
}

/* language switcher — a single <select> (see i18n.js's renderLangSwitcher)
   rather than one pill button per language: a row of pills stops scaling
   once there are more than a handful of languages (wraps awkwardly,
   crowds the topbar), where a dropdown stays a single compact control no
   matter how many SUPPORTED_LANGS grows to. */
.lang-switcher select{
  appearance:auto; border:1px solid var(--accent-dim); border-radius:999px;
  background:var(--panel); color:var(--ink);
  font-family:"Work Sans",sans-serif; font-size:12.5px; font-weight:500;
  padding:6px 10px; cursor:pointer;
}
.lang-switcher select:focus-visible{ outline:2px solid var(--accent); outline-offset:2px; }

/* account status widget (account.js) — "Sign in with Google" link for an
   anonymous visitor, or a compact badge (avatar + name) that opens a
   dropdown ("Profile", "Sign out") once signed in, rather than spelling
   both out inline — this is what actually keeps the topbar from crowding
   out the title/language picker on a narrow phone. */
.account-status{ display:flex; align-items:center; font-size:12.5px; color:var(--ink); }
.account-menu{ position:relative; display:inline-flex; }
.account-trigger{
  display:flex; align-items:center; gap:6px; appearance:none; cursor:pointer;
  border:1px solid var(--accent-dim); background:transparent; border-radius:999px;
  padding:4px 10px 4px 5px; font-family:"Work Sans",sans-serif; font-size:12.5px; color:var(--ink);
}
.account-trigger:hover{ border-color:var(--accent); }
.account-avatar{ width:22px; height:22px; border-radius:50%; flex:none; object-fit:cover; }
.account-name{ font-weight:600; max-width:120px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.account-caret{ font-size:9px; color:var(--ink-muted); }
.account-dropdown{
  position:absolute; top:calc(100% + 6px); inset-inline-end:0; z-index:20; min-width:140px;
  display:flex; flex-direction:column; gap:2px; padding:6px;
  background:var(--panel); border:1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  border-radius:10px; box-shadow:var(--shadow);
}
/* Author-origin .account-dropdown{display:flex} above would otherwise
   beat the browser's own [hidden]{display:none} — same cascade issue as
   .auth-field/.action elsewhere in this file. */
.account-dropdown[hidden]{ display:none; }
.account-dropdown-item{
  display:block; width:100%; text-align:start; appearance:none; border:none; background:transparent;
  font-family:"Work Sans",sans-serif; font-size:12.5px; font-weight:500; color:var(--ink); text-decoration:none;
  padding:8px 10px; border-radius:7px; cursor:pointer;
}
.account-dropdown-item:hover{ background:color-mix(in srgb, var(--accent) 16%, transparent); color:var(--accent); }
.account-dropdown-item:focus-visible{ outline:2px solid var(--accent); outline-offset:1px; }
/* Sized to sit inline with the "Deck" heading (see .deck-head) rather
   than as a big standalone footer button — it used to be a large
   footer-style button (15.5px/13px padding) before moving up here, which
   read as oversized next to the compact heading/count it now sits beside. */
.new-deck{
  font-size:12.5px; font-weight:600;
  padding:6px 12px; border-radius:9px;
  display:inline-flex; align-items:center; gap:6px;
}
.new-deck svg{ width:14px; height:14px; flex:none; }

.theme-row{ display:flex; gap:10px; flex-wrap:wrap; }
.theme-pill{
  appearance:none; border:1px solid var(--accent-dim); background:var(--panel); color:var(--ink);
  font-family:"Work Sans",sans-serif; font-size:13.5px; font-weight:500;
  padding:9px 16px; border-radius:999px; cursor:pointer;
  display:flex; align-items:center; gap:8px;
  transition:border-color .15s ease, transform .1s ease;
}
.theme-pill .dot{ width:9px; height:9px; border-radius:50%; background:var(--pill-accent, var(--accent)); flex:none; }
.theme-pill:hover{ transform:translateY(-1px); }
.theme-pill:focus-visible{ outline:2px solid var(--accent); outline-offset:2px; }
.theme-pill[aria-pressed="true"]{
  border-color:var(--pill-accent, var(--accent));
  background:color-mix(in srgb, var(--pill-accent, var(--accent)) 16%, var(--panel));
  font-weight:600;
}

/* ---------- deck pile / your card, one row ---------- */
/* one deck, one box: the pile and the opened card share the same stage
   (see .combined-card below) rather than living in separate panels, so
   both are always visible together at any viewport size/orientation. */
.decks{ width:100%; display:flex; justify-content:center; }

/* Width must be set explicitly here, not left to shrink-to-fit: without it
   the panel was collapsing to its narrowest child's intrinsic width (the
   Toss/Gather/No./Random row), which then bottlenecked stage-wrap's own
   width:100% down to that same narrow size regardless of --stage-max. */
.deck-panel{ display:flex; flex-direction:column; gap:12px; width:100%; max-width:var(--stage-max); margin:0 auto; }
.deck-head{ display:flex; align-items:baseline; gap:10px; flex-wrap:wrap; }
.deck-head h2{ font-size:19px; font-weight:600; font-style:italic; }
.deck-sub{ font-size:11.5px; color:var(--ink-muted); font-variant-numeric:tabular-nums; }
/* Pushes the Shuffle button to the far right of the heading row — margin-
   left:auto on the one flex item that should claim the remaining space,
   rather than restructuring deck-head's layout. align-self:center (not
   the row's own baseline alignment, which suits the h2/deck-sub text
   pairing but would look wrong for a button) keeps it vertically centered
   against the italic serif heading next to it. */
.deck-head .new-deck{ margin-left:auto; align-self:center; }

/* On a narrow phone the heading + card count + full "Shuffle" button text
   don't fit on deck-head's one row, so the button (last in source order,
   pushed out by margin-left:auto) wraps onto its own line below instead
   of sitting beside the heading as intended. Dropping to an icon-only
   button here is what actually buys back enough width to keep everything
   on one line — further padding/font tweaks alone couldn't close that
   gap. The accessible name doesn't change: aria-label (see index.html)
   already carries "Shuffle" independently of this visually-hidden label
   span, so screen readers are unaffected by hiding it here. */
@media (max-width:480px){
  .new-deck{ padding:7px 9px; gap:0; }
  .new-deck-label{ display:none; }
}

/* .deck-controls' four items (Toss/Gather/No./Random) already wrap via
   flex-wrap when they don't fit one row — but at .action's normal size
   that threshold comes quickly for a language with longer button words
   than English (e.g. Ukrainian "Розкидати"/"Випадкова" next to "Toss"/
   "Random"), wrapping into a lopsided two-line stack on an ordinary
   phone where English still fit on one line. Shrinking the controls
   specifically (not .action everywhere, which is also used for much
   bigger CTAs like "Create your profile") buys back enough width that
   every supported language's labels fit on one row at this width. */
@media (max-width:480px){
  .deck-controls{ gap:6px; }
  .deck-controls .action{ padding:7px 10px; font-size:11.5px; }
  .number-form input{ width:40px; padding:7px 6px; font-size:12.5px; }
}

.mode-switch{
  display:flex; border:1px solid var(--accent-dim); border-radius:999px; overflow:hidden;
}
.mode-btn{
  appearance:none; border:none; background:transparent; color:var(--ink-muted);
  font-family:"Work Sans",sans-serif; font-size:11.5px; font-weight:500;
  padding:6px 12px; cursor:pointer; transition:background .15s ease, color .15s ease;
}
.mode-btn[aria-pressed="true"]{ background:var(--accent); color:var(--ground); font-weight:600; }
.mode-btn:focus-visible{ outline:2px solid var(--accent); outline-offset:2px; }
.mode-btn:disabled{ opacity:.4; cursor:not-allowed; }
.mode-btn:disabled:hover{ background:transparent; }

.stage-wrap{
  position:relative;
  width:100%; max-width:var(--stage-max); margin:0 auto;
  background:radial-gradient(ellipse at 50% 20%, color-mix(in srgb, var(--accent) 10%, transparent), transparent 60%), var(--ground-raised);
  border-radius:18px; padding:4px; box-shadow:var(--shadow);
}
.stage{ position:relative; width:100%; aspect-ratio:5/7; overflow:hidden; border-radius:14px; cursor:pointer; }
.stage:focus-visible, .combined-card:focus-visible{ outline:3px solid var(--accent); outline-offset:3px; }
.stage::before{
  content:""; position:absolute; inset:0;
  background-image:radial-gradient(1px 1px at 8% 15%, color-mix(in srgb, var(--accent) 70%, white), transparent),
                    radial-gradient(1px 1px at 22% 65%, color-mix(in srgb, var(--accent) 60%, white), transparent),
                    radial-gradient(1.5px 1.5px at 46% 30%, color-mix(in srgb, var(--accent) 80%, white), transparent),
                    radial-gradient(1px 1px at 68% 75%, color-mix(in srgb, var(--accent) 55%, white), transparent),
                    radial-gradient(1.5px 1.5px at 85% 20%, color-mix(in srgb, var(--accent) 70%, white), transparent),
                    radial-gradient(1px 1px at 92% 60%, color-mix(in srgb, var(--accent) 50%, white), transparent);
  opacity:.5; pointer-events:none;
}

.card{
  position:absolute; width:52%; aspect-ratio:5/7;
  left:var(--x); top:var(--y);
  transform:translate(-50%,-50%) rotate(var(--r));
  transition:left .45s cubic-bezier(.2,.8,.2,1), top .45s cubic-bezier(.2,.8,.2,1), transform .45s cubic-bezier(.2,.8,.2,1), z-index 0s;
  cursor:pointer; perspective:800px; z-index:var(--z, 1);
}
.card.selected{ z-index:80; outline:2px solid color-mix(in srgb, var(--pill-accent) 70%, transparent); outline-offset:2px; border-radius:9%; }
.card:hover{ z-index:70; }
.card-inner{
  position:relative; width:100%; height:100%;
  transform-style:preserve-3d;
  transition:transform .5s cubic-bezier(.3,.7,.3,1);
  border-radius:9%; box-shadow:var(--shadow);
}
/* unflipped = back showing (default); flipped = content revealed */
.card.flipped .card-inner{ transform:rotateY(180deg); }

.reveal-empty{
  font-family:"Work Sans",sans-serif; font-size:12.5px; color:var(--ink-muted);
  text-align:center; padding:0 18%; line-height:1.5;
}

.face{ position:absolute; inset:0; backface-visibility:hidden; border-radius:9%; overflow:hidden;
  border:1px solid color-mix(in srgb, var(--accent) 55%, transparent); display:flex; flex-direction:column; }

/* ---------- card back (shown first) ---------- */
.card-back{
  background:
    radial-gradient(70% 55% at 50% 42%, color-mix(in srgb, var(--pill-accent) 30%, transparent), transparent),
    repeating-linear-gradient(135deg, color-mix(in srgb, var(--pill-accent) 10%, var(--card-back-a)) 0 2px, var(--card-back-a) 2px 9px),
    linear-gradient(160deg, var(--card-back-a), var(--card-back-b));
  display:flex; align-items:center; justify-content:center;
}
.card-back::after{
  content:""; position:absolute; inset:9%;
  border:1px solid color-mix(in srgb, var(--pill-accent) 55%, transparent);
  border-radius:6%;
  pointer-events:none;
}
.card-back-owl{
  display:block; width:46%; aspect-ratio:1/1; position:relative; z-index:1;
  opacity:.92; background-color:var(--pill-accent);
  -webkit-mask-image:url(/card-back-owl.png); mask-image:url(/card-back-owl.png);
  -webkit-mask-size:contain; mask-size:contain;
  -webkit-mask-repeat:no-repeat; mask-repeat:no-repeat;
  -webkit-mask-position:center; mask-position:center;
}
.card-num{
  position:absolute; top:5%; left:6%; z-index:2;
  font-family:"Work Sans",sans-serif; font-variant-numeric:tabular-nums; font-size:9px;
  color:color-mix(in srgb, var(--pill-accent) 85%, white);
  background:rgba(0,0,0,.35); padding:2px 5px; border-radius:4px; letter-spacing:.04em;
}

/* ---------- revealed content ---------- */
.card-content{ transform:rotateY(180deg); background:var(--card-back-a); }
.card-content img{ width:100%; height:100%; object-fit:cover; display:block; }
.card-content.verse-face{ background:var(--panel); padding:8% 9%; justify-content:space-between; }
.card-content .tag{ font-size:8px; text-transform:uppercase; letter-spacing:.08em; color:var(--pill-accent); font-weight:600; }
.card-content .phrase{
  font-family:"Spectral",Georgia,serif; font-style:italic;
  font-size:clamp(7px, 1.4vw, 12px); line-height:1.32; color:var(--ink);
  overflow:hidden; display:-webkit-box; -webkit-line-clamp:7; -webkit-box-orient:vertical;
}
.card-content .cite{ font-size:7px; color:var(--ink-muted); letter-spacing:.02em; }
.card-content .img-tag{
  position:absolute; bottom:5%; left:6%;
  font-size:8px; text-transform:uppercase; letter-spacing:.06em;
  color:#F5ECD8; background:rgba(20,15,8,.55); padding:2px 7px; border-radius:5px;
}

/* ---------- controls ---------- */
.deck-controls{ display:flex; flex-wrap:wrap; gap:8px; align-items:center; justify-content:center; width:100%; max-width:var(--stage-max); margin:0 auto; }
/* Bare .action (not button.action) deliberately — this class is used on
   both <button class="action"> AND <a class="action"> throughout the site
   (nav links, "Create your profile", every page-footer link, the legal
   footer, etc.). Tag-qualifying it to button.action, as this was written
   until now, silently excluded every <a class="action"> from all of this
   styling — they fell back to the browser's bare default link color
   (blue/purple), unreadably low-contrast against a dark background and
   visually broken against the light one. text-decoration:none and
   display:inline-block are needed here specifically for the <a> case —
   a <button> doesn't need either, but doesn't mind them either. */
.action{
  display:inline-block; appearance:none; border:1px solid var(--accent-dim); background:var(--accent); color:var(--ground);
  font-family:"Work Sans",sans-serif; font-weight:600; font-size:13px;
  padding:9px 15px; border-radius:9px; cursor:pointer; text-decoration:none;
  transition:transform .1s ease, filter .15s ease;
}
.action.secondary{ background:transparent; color:var(--ink); }
.action:hover{ filter:brightness(1.07); transform:translateY(-1px); }
.action:focus-visible{ outline:2px solid var(--accent); outline-offset:2px; }
/* Same author-vs-user-agent cascade issue as .auth-field above: .action's
   own display:inline-block beats the browser's [hidden]{display:none}, so
   any .action element toggled via the `hidden` attribute (e.g. #adminLink)
   needs this explicit override to actually disappear. */
.action[hidden]{ display:none; }

.number-form{ display:flex; gap:6px; align-items:center; }
.number-form input{
  width:56px; font-family:"Work Sans",sans-serif; font-variant-numeric:tabular-nums; font-size:14px;
  padding:9px 8px; border-radius:9px; border:1px solid var(--accent-dim); background:var(--panel); color:var(--ink);
}
.number-form input:focus-visible{ outline:2px solid var(--accent); outline-offset:1px; }
.number-form label{ font-size:12.5px; color:var(--ink-muted); }

/* ---------- combined card: the opened card, laid on top of the pile in
   the same stage box (see .stage) rather than a separate reveal panel —
   sized to roughly match a pile card, offset and rotated a little as if
   just tossed down, with a deeper shadow so it visibly sits above the
   pile. The image fills the whole card; text is overlaid directly on it
   (no solid background block) and relies on a heavy layered text-shadow
   to stay legible over any art. The tag is not part of the card at all —
   it's a separate label underneath the whole stage. */
.combined-card{
  position:absolute; width:60%; aspect-ratio:5/7;
  left:var(--ox, 50%); top:var(--oy, 50%);
  transform:translate(-50%,-50%) rotate(var(--or, 0deg));
  transition:left .4s cubic-bezier(.2,.8,.2,1), top .4s cubic-bezier(.2,.8,.2,1), transform .4s cubic-bezier(.2,.8,.2,1);
  border-radius:9%; overflow:hidden;
  box-shadow:0 16px 34px rgba(10,7,3,.4), var(--shadow);
  border:1px solid color-mix(in srgb, var(--accent) 55%, transparent);
  background:var(--panel);
  display:flex; flex-direction:column; justify-content:flex-end;
  z-index:90; cursor:pointer;
  /* default: light ink for a dark image (see JS luminance sampling, which
     toggles .text-on-light below for images whose lower band is pale) */
  --combined-ink:#FBF6EA; --combined-ink-dim:#F0E8D4;
  --combined-shadow:0 1px 2px rgba(0,0,0,.95), 0 3px 10px rgba(0,0,0,.85), 0 0 20px rgba(0,0,0,.6);
  --combined-shadow-soft:0 1px 3px rgba(0,0,0,.95), 0 2px 8px rgba(0,0,0,.75);
  --combined-scrim:10,7,3;
}
.combined-card[hidden]{ display:none; }
/* the image's own lower band sampled as pale — flip to dark ink with a
   light halo/scrim instead, so text stays readable either way */
.combined-card.text-on-light{
  --combined-ink:#241A08; --combined-ink-dim:#2E220D;
  --combined-shadow:0 1px 2px rgba(255,255,255,.95), 0 3px 10px rgba(255,255,255,.85), 0 0 20px rgba(255,255,255,.65);
  --combined-shadow-soft:0 1px 3px rgba(255,255,255,.95), 0 2px 8px rgba(255,255,255,.8);
  --combined-scrim:247,241,226;
}
.combined-card .combined-image{
  position:absolute; inset:0;
  background:var(--card-back-a) center/cover no-repeat;
}
.combined-card .combined-image-empty{
  background:
    radial-gradient(70% 55% at 50% 42%, color-mix(in srgb, var(--accent) 22%, transparent), transparent),
    linear-gradient(160deg, var(--card-back-a), var(--card-back-b));
}
.combined-card .combined-scrim{
  position:absolute; inset:0; pointer-events:none;
  background:linear-gradient(to top,
    rgba(var(--combined-scrim),.8) 0%,
    rgba(var(--combined-scrim),.5) 26%,
    rgba(var(--combined-scrim),0) 54%);
}
/* Display-only watermark — a small translucent owl mark over the card
   image, added purely in CSS at render time. The actual files on disk
   (content/<theme>/samples/production_sample/*.jpg) are never modified or
   re-saved; this is an overlay element, not a baked-in edit. Sits in the
   top corner, opposite the text overlay's bottom-half territory, so it
   never competes with the readable content. White + drop-shadow (rather
   than the theme's --ink, which flips color-on-color unpredictably against
   an arbitrary photo) keeps it visible against any art style. */
.combined-card .combined-watermark{
  position:absolute; top:3.5%; right:4%; z-index:1; pointer-events:none;
  width:10%; aspect-ratio:1/1;
  background-color:#fff; opacity:.55;
  -webkit-mask-image:url(/owl-watermark.png); mask-image:url(/owl-watermark.png);
  -webkit-mask-size:contain; mask-size:contain;
  -webkit-mask-repeat:no-repeat; mask-repeat:no-repeat;
  -webkit-mask-position:center; mask-position:center;
  filter:drop-shadow(0 1px 2px rgba(0,0,0,.6));
}
/* Text (and its citation) never claims more than half the card, measured
   from the bottom — even a long verse or a card whose art is mostly in the
   lower half (several of the pale ink-wash styles) stays readable without
   burying the image. Font-size already tiers down for longer text (see
   combinedFontSize in app.js); this is the hard floor under that — if a
   phrase still doesn't fit, it scrolls inside its own box rather than
   spilling further up the card. */
.combined-card .combined-overlay{
  position:relative; z-index:1;
  max-height:50%; overflow-y:auto;
  padding:9% 8% 8%;
  display:flex; flex-direction:column; gap:6px;
}
.combined-card .combined-text{
  margin:0;
  font-family:"Spectral",Georgia,serif; font-style:italic; line-height:1.34;
  color:var(--combined-ink);
  text-shadow:var(--combined-shadow);
}
.combined-card .combined-cite{
  font-family:"Work Sans",sans-serif; font-size:11px; letter-spacing:.02em;
  color:var(--combined-ink-dim);
  text-shadow:var(--combined-shadow-soft);
}


/* ---------- profile panel: a numerology/astrology-derived summary used to
   bias the deck draw toward resonant tags (see internal/cards/weighting.go).
   Two states — empty (no profile saved yet, prompts a visit to
   profile.html) and filled (compact summary + the bias slider) — toggled in
   app.js by whether profile-store.js has a cached profile. Editing always
   happens on the full profile.html form, never inline here. ---------- */
.profile-panel{
  width:100%; max-width:1020px; margin-top:22px; padding-top:22px;
  border-top:1px solid color-mix(in srgb, var(--accent) 22%, transparent);
  display:flex; flex-direction:column; gap:14px;
}
.profile-panel h3{
  font-family:"Work Sans",sans-serif; font-size:12px; font-weight:600;
  text-transform:uppercase; letter-spacing:.08em; color:var(--ink-muted); margin:0;
}
/* Mirrors .deck-head's pattern: heading + a compact control sharing one
   row, the control pushed to the far right, wrapping onto its own line
   below only if the row gets too narrow to fit both. */
.profile-head{ display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
.profile-head h2{ font-size:18px; font-weight:600; margin:0; }
.profile-head .profile-switcher{
  margin:0 0 0 auto; max-width:none; width:auto; justify-content:flex-end;
}
.profile-panel-prompt{ margin:0 0 10px; font-size:13.5px; color:var(--ink-muted); line-height:1.5; }
.profile-summary-row{ display:flex; align-items:center; gap:22px; flex-wrap:wrap; }
.profile-summary-item{ display:flex; flex-direction:column; gap:1px; }
.profile-summary-item strong{ font-family:"Fraunces",Georgia,serif; font-style:italic; font-size:16px; }
.profile-summary-item small{ font-size:10.5px; text-transform:uppercase; letter-spacing:.06em; color:var(--ink-muted); }
.profile-edit-link{ margin-left:auto; font-size:12.5px; padding:7px 14px; }
.profile-bias-row{ display:flex; align-items:center; gap:12px; }
.profile-bias-row label{ font-size:12px; color:var(--ink-muted); min-width:110px; }
.profile-bias-row input[type="range"]{ flex:1 1 auto; max-width:280px; accent-color:var(--accent); }
.profile-bias-value{ font-size:12px; font-variant-numeric:tabular-nums; color:var(--ink-muted); min-width:32px; }
.profile-bias-desc{ margin:0; font-size:12px; color:var(--ink-muted); line-height:1.5; }
.profile-match{ margin:0; font-size:13px; color:var(--ink-muted); line-height:1.5; }
.profile-match strong{ color:var(--ink); font-family:"Fraunces",Georgia,serif; font-style:italic; font-weight:600; }
.profile-bias-hint{ margin:4px 0 0; font-size:12px; }
.profile-bias-hint a{ color:var(--ink-muted); text-decoration:underline; }
.profile-bias-hint a:hover{ color:var(--ink); }

/* Secondary page links (profile/famous-profiles/admin) — deliberately kept
   out of the top of the page (see index.html) so the card gets the
   vertical space instead; they live in a quiet footer row at the very
   bottom. Shuffle itself now lives up in .deck-head instead (it acts
   directly on the deck right above it, unlike these, which navigate
   elsewhere). */
.page-footer{
  width:100%; max-width:1020px; margin-top:26px;
  display:flex; align-items:center; justify-content:center; gap:16px; flex-wrap:wrap;
}
/* The <nav> landmark wrapping these links (added for AT navigation, see
   index.html) would otherwise introduce its own flex item/box and break
   the single-row wrap above — display:contents keeps the nav's children
   flowing exactly as if the wrapper weren't there, while still exposing
   the landmark to assistive tech. Same pattern applied to
   .topbar-actions nav and .topbar nav below. */
.page-footer nav, .topbar-actions nav, .topbar nav{ display:contents; }

/* ---------- fullscreen card view: tapping the already-opened card (not
   the pile — that still draws a random card) opens this instead of
   drawing another random card, so the image and full text can actually be
   read in detail. Left/right arrow keys or a swipe draw another random
   card without leaving fullscreen; the small on-stage combined card stays
   untouched underneath. ---------- */
.fullscreen-view{
  position:fixed; inset:0; z-index:500;
  background:rgba(10,7,3,.92);
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:12px; padding:28px 16px;
}
.fullscreen-view[hidden]{ display:none; }
.fullscreen-close{
  position:fixed; top:16px; right:18px; z-index:510;
  appearance:none; border:none; background:rgba(255,255,255,.1); color:#F5ECD8;
  width:40px; height:40px; border-radius:50%; font-size:24px; line-height:1;
  cursor:pointer; display:flex; align-items:center; justify-content:center;
}
.fullscreen-close:hover{ background:rgba(255,255,255,.18); }
.fullscreen-close:focus-visible{ outline:2px solid var(--accent); outline-offset:2px; }

/* .fullscreen-card carries the "combined-card" class too (see index.html)
   so it gets the exact same face — image with text overlaid on it behind
   a scrim, same light/dark contrast logic, same 50%-height text cap — as
   the small on-stage card. This block only overrides what has to change
   for a static, centered, much bigger, unrotated presentation; everything
   else (.combined-image, .combined-scrim, .combined-overlay, etc. under
   .combined-card in the rules above) applies unchanged. */
.fullscreen-card{
  /* must stay a positioned ancestor (relative, not static) — its children
     (.combined-image, .combined-scrim) are position:absolute and need
     THIS box as their containing block, not the full-viewport backdrop */
  position:relative; left:auto; top:auto; transform:none !important;
  width:100%; max-width:min(90vw, calc(88vh * 5 / 7), 720px);
  flex:0 1 auto; cursor:default;
}
.fullscreen-hint{
  font-size:11.5px; color:rgba(245,236,216,.6); text-align:center; margin:0;
}

@media (prefers-reduced-motion: reduce){ .card, .card-inner{ transition:none; } }

/* ---------- profile page: numerology + astrology + transits ---------- */
.profile-switcher{
  width:100%; max-width:720px; margin:0 auto 16px;
  display:flex; align-items:center; gap:10px; flex-wrap:wrap; justify-content:center;
}
.profile-switcher[hidden]{ display:none; }
.profile-switcher label{ font-size:12.5px; color:var(--ink-muted); font-weight:500; }
.profile-switcher select{
  font-family:"Work Sans",sans-serif; font-size:13.5px;
  padding:8px 10px; border-radius:9px; border:1px solid var(--accent-dim);
  background:var(--ground); color:var(--ink);
}

/* Generic small-dialog pattern (currently just "+ Add profile", see
   profile.js) — a fixed full-viewport backdrop behind a centered card,
   in the same spirit as .fullscreen-view's own hand-rolled modal rather
   than the native <dialog> element, so both share one visual language. */
.modal-overlay{
  position:fixed; inset:0; background:rgba(0,0,0,.45);
  display:flex; align-items:center; justify-content:center; padding:16px; z-index:30;
}
.modal-overlay[hidden]{ display:none; }
.modal-panel{
  width:100%; max-width:360px; background:var(--panel); color:var(--ink);
  border:1px solid color-mix(in srgb, var(--accent) 35%, transparent);
  border-radius:14px; padding:20px; box-shadow:var(--shadow);
  display:flex; flex-direction:column; gap:12px;
}
.modal-panel label{ font-size:13.5px; font-weight:500; }
.modal-panel input{
  width:100%; font-family:"Work Sans",sans-serif; font-size:14px;
  padding:10px 12px; border-radius:9px; border:1px solid var(--accent-dim);
  background:var(--ground); color:var(--ink);
}
.modal-actions{ display:flex; justify-content:flex-end; gap:8px; }
.profile-form{
  width:100%; max-width:720px; margin:0 auto 28px;
  display:grid; grid-template-columns:1fr 1fr; gap:16px 20px;
  background:var(--panel); border:1px solid color-mix(in srgb, var(--accent) 35%, transparent);
  border-radius:16px; padding:24px 26px; box-shadow:var(--shadow);
}
.profile-field{ display:flex; flex-direction:column; gap:6px; min-width:0; }
.profile-field label{ font-size:12.5px; color:var(--ink-muted); font-weight:500; }
.profile-optional{ font-weight:400; opacity:.75; }
.profile-field input{
  font-family:"Work Sans",sans-serif; font-size:14px;
  padding:10px 12px; border-radius:9px; border:1px solid var(--accent-dim);
  background:var(--ground); color:var(--ink);
}
.profile-field input:focus-visible{ outline:2px solid var(--accent); outline-offset:1px; }
.profile-submit{ grid-column:1 / -1; }
.profile-submit button{ width:100%; font-size:15px; padding:13px; }

.profile-field-wide{ grid-column:1 / -1; min-width:0; }
.profile-address-row{ display:flex; gap:10px; }
.profile-address-row input{ flex:1 1 auto; min-width:0; }
.profile-address-row button{ flex:none; font-size:13px; padding:10px 14px; white-space:nowrap; }
.profile-geocode-status{ margin:2px 0 0; font-size:12px; color:var(--ink-muted); min-height:1.3em; }
.profile-geocode-status.is-ok{ color:var(--status-ok); }
.profile-geocode-status.is-error{ color:var(--status-error); }

.profile-tz-offer{
  grid-column:1 / -1; margin:-8px 0 0;
  font-size:12px; color:var(--ink-muted);
  background:color-mix(in srgb, var(--accent) 10%, transparent);
  border:1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  border-radius:8px; padding:8px 12px;
}
.profile-tz-offer-btn{
  appearance:none; border:none; background:none; padding:0;
  font-family:"Work Sans",sans-serif; font-size:12px; font-weight:600;
  color:var(--accent); text-decoration:underline; cursor:pointer;
}
.profile-tz-offer-btn:disabled{ opacity:.6; cursor:default; text-decoration:none; }

@media (max-width:600px){
  .profile-form{ grid-template-columns:1fr; padding:20px 18px; }
  .profile-address-row{ flex-direction:column; }
  .profile-address-row button{ width:100%; }
}

.profile-error{
  width:100%; max-width:720px; margin:0 auto 20px; padding:12px 16px;
  background:color-mix(in srgb, var(--status-error) 16%, var(--panel)); border:1px solid var(--status-error);
  border-radius:10px; color:var(--ink); font-size:13.5px;
}

.profile-results{ width:100%; max-width:720px; margin:0 auto; display:flex; flex-direction:column; gap:22px; }
.profile-results[hidden]{ display:none; }
.result-card{
  background:var(--panel); border:1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  border-radius:14px; padding:20px 22px; box-shadow:var(--shadow);
}
.result-card h2{ font-size:18px; font-weight:600; font-style:italic; margin-bottom:10px; }
.result-sub{ font-size:12.5px; color:var(--ink-muted); margin:0 0 14px; font-variant-numeric:tabular-nums; }

.numerology-grid{ display:flex; flex-direction:column; gap:14px; }
.numerology-item{ display:flex; gap:14px; align-items:flex-start; }
.numerology-number{
  flex:none; width:44px; height:44px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  background:color-mix(in srgb, var(--accent) 18%, var(--ground));
  font-family:"Fraunces",Georgia,serif; font-style:italic; font-weight:600; font-size:18px;
  color:var(--accent);
}
.numerology-label{ font-weight:600; font-size:14px; }
.numerology-hint{ font-size:11.5px; color:var(--ink-muted); margin-bottom:3px; }
.numerology-desc{ margin:0; font-size:13.5px; line-height:1.45; }

.astro-table{ display:flex; flex-direction:column; gap:12px; }
.astro-row{ padding-bottom:12px; border-bottom:1px solid color-mix(in srgb, var(--accent) 18%, transparent); }
.astro-row:last-child{ border-bottom:none; padding-bottom:0; }
.astro-row-head{ display:flex; justify-content:space-between; align-items:baseline; gap:10px; flex-wrap:wrap; }
.astro-body{ font-weight:600; font-size:13.5px; }
.astro-sign{ font-size:13.5px; font-variant-numeric:tabular-nums; }
.astro-deg{ color:var(--ink-muted); font-size:12px; }
.astro-desc{ margin:4px 0 0; font-size:13px; color:var(--ink); line-height:1.4; }
.astro-role{ margin:2px 0 0; font-size:12px; color:var(--ink-muted); font-style:italic; }

.transit-list{ display:flex; flex-direction:column; gap:14px; }
.transit-row{ padding-bottom:14px; border-bottom:1px solid color-mix(in srgb, var(--accent) 18%, transparent); }
.transit-row:last-child{ border-bottom:none; padding-bottom:0; }
.transit-head{ display:flex; justify-content:space-between; gap:10px; font-weight:600; font-size:13.5px; flex-wrap:wrap; }
.transit-orb{ font-weight:400; font-size:12px; color:var(--ink-muted); font-variant-numeric:tabular-nums; }
.transit-desc{ margin:4px 0; font-size:13px; }
.transit-role{ margin:2px 0; font-size:12px; color:var(--ink-muted); }

/* the lead "newspaper column" feature — set apart from the technical
   result cards with a warmer border and serif prose, like a real
   horoscope column rather than a data table. */
.prognosis-card{
  background:color-mix(in srgb, var(--accent) 7%, var(--panel));
  border-color:color-mix(in srgb, var(--accent) 55%, transparent);
}
.prognosis-text{
  margin:0; font-family:"Spectral",Georgia,serif; font-style:italic;
  font-size:15.5px; line-height:1.6; color:var(--ink); white-space:pre-line;
}

.profile-disclaimer{
  margin:4px 0 0; font-size:11.5px; line-height:1.5; color:var(--ink-muted);
  text-align:center; padding-top:4px;
}

/* "At a Glance": the two headline descriptors (Sun sign + Life Path)
   reduced to scannable keyword chips, plus any real people who share
   this exact (sign, life path) combo — see internal/profiles.Matches. */
.keyword-chips{ display:flex; flex-wrap:wrap; gap:8px; margin:0 0 16px; }
.keyword-chip{
  display:inline-block; padding:5px 13px; border-radius:999px;
  border:1px solid var(--accent-dim);
  background:color-mix(in srgb, var(--accent) 14%, var(--panel));
  font-size:12.5px; font-weight:600; color:var(--ink); letter-spacing:.01em;
}
.profile-matches-label{ margin:0 0 10px; font-size:12.5px; color:var(--ink-muted); }
.profile-matches-empty{ margin:0; font-size:13px; color:var(--ink-muted); }
.profile-match-person{ padding-bottom:12px; margin-bottom:12px; border-bottom:1px solid color-mix(in srgb, var(--accent) 18%, transparent); }
.profile-match-person:last-child{ border-bottom:none; padding-bottom:0; margin-bottom:0; }
.profile-match-name{ font-weight:600; font-size:13.5px; }
.profile-match-field{ font-size:12px; color:var(--ink-muted); font-style:italic; margin-left:6px; }
.profile-match-blurb{ margin:3px 0 0; font-size:13px; line-height:1.4; color:var(--ink); }

/* a person's real name, linking out to their Wikipedia page — used on the
   famous-profiles table, the profile page's match list, and the deck
   panel's "you share this profile with..." line. Every row's link is
   pre-resolved and verified server-side (famous_people.csv's
   wikipedia_url column), never guessed client-side. */
a.wiki-link{ color:inherit; text-decoration-color:var(--accent-dim); text-underline-offset:2px; }
a.wiki-link:hover{ text-decoration-color:var(--ink); }

/* ---------- famous-profiles.html: a QA/review page for the curated
   sign+life-path dataset (internal/profiles) used to bias deck draws and
   surface "you share a profile with..." matches — see docs on
   internal/profiles/famous.go. Not part of the main card-drawing flow. ---------- */
.fp-summary{
  width:100%; max-width:1020px; margin:0 auto 24px; font-size:14px; color:var(--ink-muted);
}
.fp-summary strong{ color:var(--ink); font-family:"Fraunces",Georgia,serif; font-style:italic; }
.fp-grid-section, .fp-list-section{ width:100%; max-width:1020px; margin:0 auto 32px; }
.fp-grid-section h3, .fp-list-section h3{
  font-family:"Work Sans",sans-serif; font-size:13px; font-weight:600;
  text-transform:uppercase; letter-spacing:.07em; color:var(--ink-muted); margin:0 0 6px;
}
.fp-grid-note{ margin:0 0 12px; font-size:12.5px; color:var(--ink-muted); }
.fp-grid-wrap, .fp-table-wrap{ width:100%; overflow-x:auto; border-radius:10px; }
table.fp-grid{ border-collapse:collapse; font-size:12px; font-variant-numeric:tabular-nums; }
table.fp-grid th{
  padding:6px 9px; font-weight:600; color:var(--ink-muted); text-align:center;
  background:var(--panel); position:sticky; top:0;
}
table.fp-grid th:first-child{ text-align:left; position:sticky; left:0; z-index:1; }
table.fp-grid td{
  padding:6px 9px; text-align:center; border:1px solid color-mix(in srgb, var(--accent) 16%, transparent);
  min-width:30px;
}
.fp-cell-empty{ background:color-mix(in srgb, var(--status-error) 22%, var(--ground)); color:var(--status-error); font-weight:600; }
.fp-cell-filled{ background:color-mix(in srgb, var(--accent) 12%, var(--panel)); }
.fp-filters{ margin-bottom:10px; }
.fp-filters input{
  width:100%; max-width:360px; font-family:"Work Sans",sans-serif; font-size:13px;
  padding:9px 12px; border-radius:9px; border:1px solid var(--accent-dim);
  background:var(--panel); color:var(--ink);
}
.fp-list-count{ font-weight:400; text-transform:none; letter-spacing:0; opacity:.7; }
table.fp-table{ border-collapse:collapse; width:100%; font-size:12.5px; }
table.fp-table th{
  padding:8px 10px; text-align:left; font-weight:600; color:var(--ink-muted);
  border-bottom:1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  white-space:nowrap;
}
table.fp-table td{
  padding:7px 10px; border-bottom:1px solid color-mix(in srgb, var(--accent) 12%, transparent);
  vertical-align:top;
}
table.fp-table .fp-blurb{ color:var(--ink-muted); max-width:360px; }

/* ---------- admin page: deactivate (not delete) themes/phrases/images —
   see internal/admin and cmd/metacards-web/main.go's requireAdmin. ---------- */
.admin-themes-section, .admin-detail-section{ width:100%; max-width:1020px; margin:0 auto 32px; }
.admin-themes-section h3{
  font-family:"Work Sans",sans-serif; font-size:13px; font-weight:600;
  text-transform:uppercase; letter-spacing:.07em; color:var(--ink-muted); margin:0 0 6px;
}
.admin-note{ margin:0 0 14px; font-size:12.5px; color:var(--ink-muted); }

.admin-toggle-btn{
  appearance:none; border:1px solid var(--accent-dim); border-radius:999px;
  padding:5px 13px; font-family:"Work Sans",sans-serif; font-size:11.5px; font-weight:600;
  background:color-mix(in srgb, var(--accent) 16%, var(--panel)); color:var(--ink); cursor:pointer;
  flex:none;
}
.admin-toggle-btn[aria-pressed="false"]{
  background:color-mix(in srgb, var(--status-error) 16%, var(--panel)); border-color:var(--status-error); color:var(--status-error);
}
.admin-toggle-btn:disabled{ opacity:.5; cursor:wait; }

.admin-theme-list{ display:flex; flex-direction:column; gap:10px; }
.admin-theme-row{
  display:flex; align-items:center; gap:14px; flex-wrap:wrap;
  padding:12px 16px; border-radius:12px; background:var(--panel);
  border:1px solid color-mix(in srgb, var(--accent) 25%, transparent);
}
.admin-theme-row.admin-inactive{ opacity:.6; }
.admin-theme-label{ font-weight:600; font-size:14px; flex:1 1 auto; min-width:140px; }
.admin-theme-stats{ font-size:12px; color:var(--ink-muted); font-variant-numeric:tabular-nums; }

.admin-users-list{ display:flex; flex-direction:column; gap:8px; }
.admin-user-row{
  display:flex; align-items:center; gap:14px; flex-wrap:wrap;
  padding:10px 16px; border-radius:12px; background:var(--panel);
  border:1px solid color-mix(in srgb, var(--accent) 25%, transparent);
}
.admin-user-row.admin-inactive{ opacity:.6; }
.admin-user-email{ font-weight:600; font-size:13.5px; flex:1 1 auto; min-width:160px; }
.admin-user-meta{ font-size:12px; color:var(--ink-muted); font-variant-numeric:tabular-nums; }

.admin-blocklist-add{ display:flex; gap:8px; margin-bottom:12px; }
.admin-blocklist-add input{
  flex:1 1 auto; font-family:"Work Sans",sans-serif; font-size:13.5px;
  padding:8px 11px; border-radius:9px; border:1px solid var(--accent-dim);
  background:var(--ground); color:var(--ink);
}
.admin-blocklist{ display:flex; flex-wrap:wrap; gap:8px; }
.admin-blocklist-item{
  display:flex; align-items:center; gap:8px;
  font-size:12.5px; font-family:"Work Sans",sans-serif; font-variant-numeric:tabular-nums;
  padding:6px 8px 6px 12px; border-radius:999px;
  border:1px solid var(--accent-dim); background:var(--panel);
}
.admin-blocklist-item button{
  appearance:none; border:none; background:transparent; color:var(--ink-muted);
  cursor:pointer; font-size:14px; line-height:1; padding:2px;
}
.admin-blocklist-item button:hover{ color:var(--status-error); }

.admin-detail-section{
  padding:18px 20px; border-radius:14px; background:var(--panel);
  border:1px solid color-mix(in srgb, var(--accent) 30%, transparent);
}
.admin-detail-head{ display:flex; align-items:center; justify-content:space-between; gap:12px; margin-bottom:12px; }
.admin-detail-head h3{ font-size:18px; font-weight:600; font-style:italic; }
.admin-detail-tabs{ display:flex; gap:8px; margin-bottom:14px; }
.admin-filter{
  width:100%; max-width:420px; font-family:"Work Sans",sans-serif; font-size:13px;
  padding:9px 12px; border-radius:9px; border:1px solid var(--accent-dim);
  background:var(--ground); color:var(--ink); margin-bottom:12px;
}

.admin-phrase-list{ display:flex; flex-direction:column; gap:8px; max-height:60vh; overflow-y:auto; }
.admin-phrase-row{
  display:flex; align-items:flex-start; gap:12px; padding:10px 12px; border-radius:10px;
  border:1px solid color-mix(in srgb, var(--accent) 16%, transparent);
}
.admin-phrase-row.admin-inactive{ opacity:.55; }
.admin-phrase-body{ min-width:0; }
.admin-phrase-citation{ font-size:11.5px; color:var(--ink-muted); }
.admin-phrase-text{ font-size:13.5px; line-height:1.4; margin:2px 0; }
.admin-phrase-tags{ font-size:11px; color:var(--pill-accent, var(--accent)); text-transform:uppercase; letter-spacing:.04em; }
.admin-edit-btn{
  appearance:none; border:none; background:none; color:var(--accent);
  font-family:"Work Sans",sans-serif; font-size:11.5px; font-weight:600;
  cursor:pointer; padding:4px 0; margin-top:4px; text-decoration:underline;
}
.admin-edit-form{
  margin-top:10px; padding:12px; border-radius:10px;
  background:var(--ground); border:1px solid var(--accent-dim);
  display:flex; flex-direction:column; gap:6px;
}
.admin-edit-heading{ font-weight:600; font-size:12.5px; margin-bottom:2px; }
.admin-edit-label{ font-size:11px; color:var(--ink-muted); margin-top:4px; }
.admin-edit-textarea{
  width:100%; font-family:"Work Sans",sans-serif; font-size:13px; line-height:1.4;
  padding:8px 10px; border-radius:8px; border:1px solid var(--accent-dim);
  background:var(--panel); color:var(--ink); resize:vertical;
}
.admin-edit-actions{ display:flex; align-items:center; gap:10px; margin-top:6px; }
.admin-edit-status{ font-size:12px; color:var(--status-error); }

.admin-image-grid{
  display:grid; grid-template-columns:repeat(auto-fill, minmax(140px, 1fr)); gap:12px;
  max-height:70vh; overflow-y:auto;
}
.admin-image-cell{
  border-radius:10px; overflow:hidden; border:1px solid color-mix(in srgb, var(--accent) 20%, transparent);
  background:var(--ground);
}
.admin-image-cell.admin-inactive{ opacity:.5; }
.admin-image-cell img{ width:100%; aspect-ratio:5/7; object-fit:cover; display:block; }
.admin-image-meta{ display:flex; align-items:center; justify-content:space-between; gap:6px; padding:6px 8px; }

/* ---------- welcome / cover page (guests land here, see auth.go's
   requireLoginForPages) ---------- */
.welcome-hero{
  width:100%; max-width:980px; margin:18px 0 8px;
  display:grid; grid-template-columns:1.1fr 1fr; gap:36px; align-items:center;
  background:radial-gradient(ellipse at 30% 20%, color-mix(in srgb, var(--accent) 12%, transparent), transparent 60%);
  border-radius:20px; padding:18px;
}
.welcome-hero-text{ display:flex; flex-direction:column; align-items:flex-start; gap:14px; text-align:left; }
.welcome-tagline{
  font-family:"Fraunces",Georgia,serif; font-style:italic; font-weight:600;
  font-size:clamp(24px,3.4vw,34px); margin:0;
}
.welcome-pitch{ margin:0; font-size:14.5px; line-height:1.65; color:var(--ink-muted); }
/* The sign-in button is the page's one job — give it real weight (shadow,
   size) rather than treating it like a secondary link, and let it fill
   the width on mobile so it's the unmissable thing a thumb lands on. */
.welcome-cta{
  display:inline-block; appearance:none; border:1px solid var(--accent-dim);
  background:var(--accent); color:var(--ground); text-decoration:none;
  font-family:"Work Sans",sans-serif; font-weight:700; font-size:16.5px;
  padding:16px 34px; border-radius:12px; cursor:pointer;
  box-shadow:var(--shadow);
  transition:transform .1s ease, filter .15s ease, box-shadow .15s ease;
}
.welcome-cta:hover{ filter:brightness(1.07); transform:translateY(-1px); box-shadow:0 14px 30px rgba(36,29,20,.28); }
.welcome-cta:focus-visible{ outline:2px solid var(--accent); outline-offset:2px; }
.welcome-cta-note{ margin:0; font-size:11.5px; color:var(--ink-muted); }

/* Email+password alternative to the Google button above (see auth.js) —
   given its own card panel (same visual language as .welcome-steps/
   .welcome-decks below) rather than floating loose under the Google
   button, so it reads as a deliberate second option instead of an
   afterthought tacked onto the hero text. Still visually quieter than
   .welcome-cta (no shadow, bordered rather than filled submit button) so
   Google stays the primary path. */
.welcome-auth-panel{
  width:100%; max-width:320px;
  background:var(--panel); border:1px solid color-mix(in srgb, var(--accent) 25%, transparent);
  border-radius:14px; padding:18px 20px;
}
.auth-divider{
  margin:0 0 14px; color:var(--ink-muted); font-size:11.5px;
  text-transform:uppercase; letter-spacing:.06em; text-align:center;
}
.auth-form{ display:flex; flex-direction:column; gap:12px; }
.auth-field{ display:flex; flex-direction:column; gap:5px; }
/* Without this, the bare .auth-field{display:flex} rule above — an
   AUTHOR-origin rule — overrides the browser's own [hidden]{display:none}
   default, which is USER-AGENT-origin: author rules always beat
   user-agent rules in the cascade regardless of specificity, so any
   .auth-field this script toggles `hidden` on (the name field outside
   register mode, the password field in forgot-password mode — see
   auth.js's render()) stayed visibly rendered no matter what `hidden`
   was set to. This single override, specific enough (class+attribute) to
   win over the plain .auth-field rule, is what actually makes `hidden`
   work again. */
.auth-field[hidden]{ display:none; }
.auth-field label{ font-size:12px; color:var(--ink-muted); font-weight:500; }
.auth-field input{
  width:100%; font-family:"Work Sans",sans-serif; font-size:14px;
  padding:10px 12px; border-radius:9px; border:1px solid var(--accent-dim);
  background:var(--ground); color:var(--ink);
}
.auth-field input:focus-visible{ outline:2px solid var(--accent); outline-offset:1px; }
.auth-submit{ width:100%; font-size:14px; padding:11px; margin-top:2px; }
.auth-links{
  display:flex; justify-content:space-between; gap:10px; flex-wrap:wrap;
  margin-top:4px; padding-top:12px; border-top:1px solid color-mix(in srgb, var(--accent) 18%, transparent);
}
.auth-link{
  appearance:none; border:none; background:transparent; color:var(--ink-muted);
  font-family:"Work Sans",sans-serif; font-size:12px; text-decoration:underline; cursor:pointer; padding:2px 0;
}
.auth-link:hover{ color:var(--ink); }
.auth-link:focus-visible{ outline:2px solid var(--accent); outline-offset:2px; border-radius:3px; }
.auth-message{
  margin:0; padding:9px 11px; border-radius:8px; font-size:12.5px; line-height:1.5;
}
.auth-message.is-error{ color:var(--status-error); background:color-mix(in srgb, var(--status-error) 12%, transparent); }
.auth-message.is-ok{ color:var(--status-ok); background:color-mix(in srgb, var(--status-ok) 12%, transparent); }

/* Decorative fanned showcase of real, live card art (see welcome.js) — a
   non-interactive preview of what the app itself looks like, not just
   marketing copy. aspect-ratio keeps a stable reserved box so the layout
   doesn't jump once the async fetch fills it in. */
.welcome-fan{ position:relative; width:100%; max-width:440px; aspect-ratio:2.2/1; margin:0 auto; }
.welcome-fan-card{
  position:absolute; width:26%; aspect-ratio:5/7; top:14%;
  border-radius:10px; overflow:hidden; box-shadow:var(--shadow);
  border:2px solid color-mix(in srgb, var(--pill-accent, var(--accent)) 55%, transparent);
  transition:transform .2s ease, z-index 0s;
}
.welcome-fan-card:hover{ transform:translateY(-10px) scale(1.04); z-index:10; }
.welcome-fan-card img{ width:100%; height:100%; object-fit:cover; display:block; }
.welcome-fan-card:nth-child(1){ left:0%; top:22%; transform:rotate(-14deg); z-index:1; }
.welcome-fan-card:nth-child(2){ left:16%; top:6%; transform:rotate(-7deg); z-index:2; }
.welcome-fan-card:nth-child(3){ left:32%; top:0%; transform:rotate(0deg); z-index:3; }
.welcome-fan-card:nth-child(4){ left:48%; top:6%; transform:rotate(7deg); z-index:2; }
.welcome-fan-card:nth-child(5){ left:64%; top:22%; transform:rotate(14deg); z-index:1; }
.welcome-fan-card:nth-child(1):hover, .welcome-fan-card:nth-child(2):hover,
.welcome-fan-card:nth-child(4):hover, .welcome-fan-card:nth-child(5):hover{ transform:translateY(-10px) scale(1.04) rotate(0deg); }

.welcome-steps, .welcome-decks{
  width:100%; max-width:720px; margin:26px auto 0;
  background:var(--panel); border:1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  border-radius:14px; padding:22px 24px; box-shadow:var(--shadow);
}
.welcome-steps h2, .welcome-decks h2{ font-size:17px; font-weight:600; font-style:italic; margin:0 0 14px; }
.welcome-step-body{ margin:2px 0 0; font-size:13px; color:var(--ink-muted); line-height:1.55; }

.welcome-disclaimer{
  width:100%; max-width:720px; margin:22px auto 0;
  font-size:11.5px; line-height:1.55; color:var(--ink-muted); text-align:center;
}

/* ---------- legal pages (impressum/privacy) + the small footer linking
   to them from every page, see legal-footer.js ---------- */
.legal-section{
  width:100%; max-width:720px; margin:0 auto 32px;
  background:var(--panel); border:1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  border-radius:14px; padding:26px 30px; box-shadow:var(--shadow);
  font-size:14px; line-height:1.6; color:var(--ink);
}
.legal-section h2{
  font-size:16px; font-weight:600; font-style:italic; margin:22px 0 8px;
}
.legal-section h2:first-child{ margin-top:0; }
.legal-section p{ margin:0 0 8px; color:var(--ink-muted); }
.legal-section a{ color:var(--accent); }

.legal-footer{
  width:100%; display:flex; justify-content:center; gap:16px;
  margin:28px 0 10px; font-size:11.5px; color:var(--ink-muted);
}
.legal-footer a{ color:inherit; }

/* Shrinks the language picker and the signed-in account badge specifically
   on narrow phones — both already fit comfortably on tablet/desktop widths
   where .topbar's row layout (see above) has plenty of room, so this only
   needs to kick in once space actually gets tight. */
@media (max-width:480px){
  .lang-switcher select{ font-size:11px; padding:4px 8px; }
  .account-trigger{ padding:3px 8px 3px 4px; gap:4px; }
  .account-avatar{ width:18px; height:18px; }
  .account-name{ max-width:72px; font-size:11.5px; }
}

@media (max-width:760px){
  .welcome-topbar{ gap:8px; margin-bottom:8px; }
  .welcome-topbar .brand h1{ font-size:22px; }
  .welcome-hero{ grid-template-columns:1fr; text-align:center; padding:12px; }
  .welcome-hero-text{ align-items:center; text-align:center; }
  /* The CTA is the page's one job — .welcome-hero-text (tagline, pitch,
     CTA) already comes before .welcome-fan in the markup, and both now
     keep their default order (no reordering), so the sign-in button
     lands well above the fold instead of below the decorative fan. */
  .welcome-fan{ max-width:320px; }
  .welcome-cta{ width:100%; text-align:center; }
  /* The panel itself stays centered in the now-centered hero column, but
     its own contents (labels, inputs, links) must NOT inherit
     text-align:center from .welcome-hero-text above — a centered label
     over a left-aligned input looks broken, not polished. */
  .welcome-auth-panel{ margin:0 auto; text-align:left; }
}
.admin-image-filename{ font-size:10px; color:var(--ink-muted); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
