/* ──────────────────────────────────────────────────────────────────────────
 * theme.css — single source of truth for the Starveil app's visual design.
 *
 * Everything visual (palette, type, spacing, shape) is a CSS custom property
 * defined in :root below. Widgets and backend pages consume these via var(...)
 * and must NOT hardcode colours, fonts, or radii. To restyle the whole app,
 * edit the tokens here — nothing else.
 *
 * Like config.js, this file is the canonical copy. It is propagated into every
 * widget (widgets/<name>/app/css/theme.css) and the backend public pages
 * (backend/public/css/theme.css) by `node scripts/sync-theme.js`. Run that
 * after every edit, before `zet pack`. Never edit a synced copy by hand.
 *
 * The look: a clean white page, black ink outlines, flat fills in the StarVeil
 * brand palette (Golden Yellow for the highlight, Deep Royal Purple, Pink, Lime,
 * Blue Gray — docs/vision/brand.md) with an extruded edge in a neighbouring hue,
 * hand-lettered caps for headings. Shape and faces come from the calendar's
 * "Sugar Sketch" build; the colours were aligned to the brand book 2026-10-30.
 * See docs/conventions/styling.md.
 * ────────────────────────────────────────────────────────────────────────── */

/* The faces named below are fetched by each page's own <link> (webapp/index.html, manager/index.html;
   the public pages' copy of this file keeps its @import): a <link> in the head loads beside this sheet,
   an @import here would load after it and hold the first paint. */

:root {
  /* ── Paper + ink ── */
  --paper:      #ffffff;
  --ink:        #1d1a1f;   /* text and every outline */
  --ink-soft:   #667074;   /* secondary text (blue-gray leaning) */
  --ink-faint:  #a9b2b7;   /* placeholders, dashed "off" outlines */
  --rule:       #eef1f2;   /* hairline row dividers */

  /* ── Tones: --x fill · --x-s strong same hue (strips, icons) · --x-d extruded edge.
   *    The strong hue of pink / lav / mint / butter / fog IS the brand colour
   *    (Pink, Deep Royal Purple, Lime, Golden Yellow, Blue Gray); the fill is its tint.
   *    sky / peach / coral have no brand colour — they are functional (info, task, danger). ── */
  --pink:   #f8bfe1;  --pink-s:   #eb48a8;  --pink-d:   #b57bd0;
  --lav:    #d3c4dc;  --lav-s:    #5f2980;  --lav-d:    #c66bb4;
  --mint:   #d4edc5;  --mint-s:   #7cc257;  --mint-d:   #d9be2e;
  --butter: #f5e89f;  --butter-s: #e8cc29;  --butter-d: #ffa24c;
  --sky:    #c6e4ff;  --sky-s:    #4aa3f0;  --sky-d:    #8b8ff0;
  --peach:  #ffc993;  --peach-s:  #ff9a3c;  --peach-d:  #f2706b;
  --coral:  #ffb8b2;  --coral-s:  #e5484d;  --coral-d:  #f2706b;
  --fog:    #dfe3e5;  --fog-s:    #94a1a7;  --fog-d:    #b9c3c8;

  /* ── Surfaces ── */
  --bg:         var(--paper);
  --surface:    var(--paper);
  --surface-2:  #fffcd9;   /* Light Yellow: inset fields, hover, read-only */
  --line:       #dfe3e5;   /* soft outlines that are not ink */
  --line-soft:  var(--rule);

  /* ── Accent — the brand highlights. Golden Yellow is the primary action and the current
   *    selection (ink text on it); Pink is for small marks; Deep Royal Purple is the only
   *    brand colour legible as text on white. ── */
  --accent:       var(--pink-s);
  --accent-ink:   #5f2980;   /* accent text / links on white */
  --accent-wash:  var(--butter-s);

  /* ── Status. The base colour is for text and marks (readable on white);
   *    the -wash is the tone fill a chip or banner sits on (with an ink outline). ── */
  --positive:  #2f7a22;  --positive-wash: var(--mint);
  --negative:  #d93a40;  --negative-wash: var(--coral);
  --warning:   #8f7400;  --warning-wash:  var(--butter);
  --info:      #2a7fd0;  --info-wash:     var(--sky);
  --shift:     var(--lav-s);  --shift-wash: var(--lav);  /* staff shifts on a calendar */

  /* Text on a dark fill (rare: the ink tooltip, the photo lightbox). */
  --on-dark:    #ffffff;

  /* ── Type ──
   * Hand  (Coming Soon): headings and names, in caps.
   * Label (Gaegu):       small caps labels, tabs, text buttons.
   * UI    (Fredoka):     everything people read — values, amounts, body, inputs.
   * Japanese falls back to Yomogi / Zen Maru Gothic.                         */
  --font-ui:    'Fredoka', 'Zen Maru Gothic', 'Hiragino Maru Gothic ProN', system-ui, sans-serif;
  --font-hand:  'Coming Soon', 'Yomogi', 'Fredoka', cursive;
  --font-label: 'Gaegu', 'Yomogi', 'Fredoka', cursive;
  /* Older names, kept so every stylesheet reads the same faces. */
  --font-serif: var(--font-ui);
  --font-sans:  var(--font-ui);

  /* Type scale (rem-based so it flexes; 1rem = 16px). */
  --fs-display: 1.45rem;   /* screen / person name (hand) */
  --fs-title:   1.0rem;    /* prominent values */
  --fs-value:   0.95rem;   /* field values */
  --fs-body:    0.875rem;  /* body / inputs */
  --fs-label:   0.6875rem; /* small sans text */
  --fs-small:   0.625rem;  /* captions, badges */
  --fs-tag:     0.9375rem; /* Gaegu caps labels (Gaegu reads small) */
  --fs-tag-sm:  0.8125rem; /* Gaegu caps on badges */

  --lh-tight:   1.2;
  --lh-body:    1.5;

  /* ── Shape ── */
  --radius:      16px;
  --radius-sm:   12px;
  --radius-pill: 999px;
  /* Hand-drawn corners: slightly uneven, for outlined cards, inputs and sheets. */
  --wob:    16px 13px 17px 12px / 13px 17px 12px 16px;
  --wob-sm: 12px 10px 13px 9px / 10px 13px 9px 12px;
  --wob-round: 50% 44% 52% 46%;

  /* Outlines */
  --edge:      2px solid var(--ink);     /* cards, inputs, buttons */
  --edge-thin: 1.5px solid var(--ink);   /* chips, badges, small round buttons */

  /* Flat by default. The extruded edge is spelled out per rule
   * (box-shadow: 3px 3px 0 <tone-d>, 3px 3px 0 2px var(--ink)) and kept for one-off
   * things: main buttons, sheets, popovers. Anything that repeats stays flat. */
  --shadow-sm:  none;
  --shadow:     4px 4px 0 var(--lav), 4px 4px 0 2px var(--ink);
  --focus-ring: 0 0 0 3px var(--accent-wash);

  /* Motion */
  --spring: cubic-bezier(.34, 1.56, .64, 1);
  --soft:   cubic-bezier(.22, 1, .36, 1);

  /* Modal/overlay scrim. */
  --scrim:      rgba(29, 26, 31, .34);
  --scrim-blur: blur(6px);   /* every pop-up blurs what it covers (ui-rules §5) */

  /* ── Layout knobs ──
   * Field-label column width is a token because JP labels need more room than
   * EN. Widen here once when the Japanese build lands — every widget follows. */
  --field-label-w: 116px;
  --content-max:   480px;   /* mobile-first column width */
  --space:         16px;    /* base gutter */

  color-scheme: light;
}

/* ── Dark: night paper and chalk ink. The same rules hold with the values turned over:
 *    the fills that carry ink text (every --x, --surface-2, --accent-wash) become deep
 *    tones so chalk reads on them; the strong hues stay bright, for marks and strips;
 *    the text colours are lifted to read on night paper. Set by the app (webapp/src/theme.js,
 *    the avatar's Appearance), never by a media query here, so a page without the app's
 *    script (checkout, the public pages) stays on white paper. ── */
:root[data-theme="dark"] {
  --paper:      #1a181e;
  --ink:        #f1ede4;   /* warm chalk, one step off white */
  --ink-soft:   #a9b2b6;
  --ink-faint:  #6d767b;
  --rule:       #2b2930;

  --pink:   #5c2449;  --pink-s:   #f062b6;  --pink-d:   #8b4fa9;
  --lav:    #3e2d4e;  --lav-s:    #c59be2;  --lav-d:    #8f4785;
  --mint:   #2b4321;  --mint-s:   #8fd16a;  --mint-d:   #85761b;
  --butter: #4a4013;  --butter-s: #e8cc29;  --butter-d: #a3601f;
  --sky:    #1e3955;  --sky-s:    #62b2f5;  --sky-d:    #4b50a8;
  --peach:  #573719;  --peach-s:  #ffa654;  --peach-d:  #a5433f;
  --coral:  #5c2627;  --coral-s:  #f0676b;  --coral-d:  #a5433f;
  --fog:    #33373a;  --fog-s:    #8f9ca2;  --fog-d:    #4d5559;

  --surface-2:  #24221b;   /* the Light Yellow paper, at night */
  --line:       #3b3941;

  --accent-ink:   #d8b6ee;
  --accent-wash:  #6e5b0c;   /* Golden Yellow deepened to carry chalk text; --butter-s stays the bright mark */

  --positive:  #8fd16a;
  --negative:  #ff7f83;
  --warning:   #e8cc29;
  --info:      #7cbcf5;

  --on-dark:    var(--paper);   /* text on an ink fill, which is now light */

  --focus-ring: 0 0 0 3px var(--butter-s);
  --scrim:      rgba(0, 0, 0, .55);

  color-scheme: dark;
}

/* Tone helpers: set --c / --cs / --cd on an element to paint it in one pastel. */
.t-pink   { --c: var(--pink);   --cs: var(--pink-s);   --cd: var(--pink-d); }
.t-lav    { --c: var(--lav);    --cs: var(--lav-s);    --cd: var(--lav-d); }
.t-mint   { --c: var(--mint);   --cs: var(--mint-s);   --cd: var(--mint-d); }
.t-butter { --c: var(--butter); --cs: var(--butter-s); --cd: var(--butter-d); }
.t-sky    { --c: var(--sky);    --cs: var(--sky-s);    --cd: var(--sky-d); }
.t-peach  { --c: var(--peach);  --cs: var(--peach-s);  --cd: var(--peach-d); }
.t-coral  { --c: var(--coral);  --cs: var(--coral-s);  --cd: var(--coral-d); }
.t-fog    { --c: var(--fog);    --cs: var(--fog-s);    --cd: var(--fog-d); }

/* ── Reset ── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

html { -webkit-tap-highlight-color: transparent; }
body {
  font-family: var(--font-ui);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  background: var(--bg);
  color: var(--ink);
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

a { color: var(--ink); text-decoration: underline 1.5px var(--pink-s); text-underline-offset: 3px; }
::selection { background: var(--butter); color: var(--ink); }
:where(button, input, select, textarea) { font-family: inherit; }
:where(button, input, select, textarea, a, [tabindex]):focus-visible { outline: none; box-shadow: var(--focus-ring); }

/* ── Branded tick box and radio: an ink box that fills mint. Zero specificity, so a
 * widget rule for a particular control always wins. ── */
:where(input[type="checkbox"], input[type="radio"]) {
  appearance: none; -webkit-appearance: none; flex: none;
  display: inline-grid; place-items: center; vertical-align: middle;
  width: 22px; height: 22px; margin: 0; background: var(--paper);
  border: 2px solid var(--ink); border-radius: 7px 6px 8px 5px; cursor: pointer;
  transition: background .15s, transform .25s var(--spring);
}
:where(input[type="radio"]) { border-radius: 50%; }
:where(input[type="checkbox"])::after {
  content: ''; width: 6px; height: 11px; margin-top: -3px;
  border: solid var(--ink); border-width: 0 2.5px 2.5px 0; transform: rotate(45deg) scale(0);
  transition: transform .25s var(--spring);
}
:where(input[type="radio"])::after {
  content: ''; width: 10px; height: 10px; border-radius: 50%; background: var(--ink);
  transform: scale(0); transition: transform .25s var(--spring);
}
:where(input[type="checkbox"], input[type="radio"]):checked { background: var(--mint); }
:where(input[type="checkbox"]):checked::after { transform: rotate(45deg) scale(1); }
:where(input[type="radio"]):checked::after { transform: scale(1); }
:where(input[type="checkbox"], input[type="radio"]):active { transform: scale(.9); }
:where(input[type="checkbox"], input[type="radio"]):disabled { opacity: .45; cursor: not-allowed; }

/* ── The star — the loading spinner, and the static mark it lands as (.star-mark) ── */
.spinner, .star-mark {
  --star-mask: url("data:image/png;base64,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");
  -webkit-mask: var(--star-mask) center / contain no-repeat;
          mask: var(--star-mask) center / contain no-repeat;
  display: inline-block;
}
.spinner {
  width: 32px; height: 32px;
  background: var(--butter-s);
  animation: star-turn 4.8s var(--spring) infinite;
}
.star-mark { background: var(--ink); }
/* .star-home = the header star the first loader lands on (star.js); hidden until it does. */
.star-home { width: 22px; height: 22px; flex: 0 0 auto; }
html.star-waiting .star-home { visibility: hidden; }
.title-star { width: 24px; height: 24px; margin-left: 2px; vertical-align: top; position: relative; top: -10px; }
/* In a tab bar the star is an end cap: it stays put while the tabs scroll under its fade. */
.tab-star { display: flex; align-items: center; flex: 0 0 auto; align-self: stretch; margin-left: auto; position: sticky; right: calc(-1 * var(--tab-star-inset, 0px)); padding: 0 var(--tab-star-inset, 0px) 0 14px; background: linear-gradient(to right, transparent, var(--tab-star-bg, var(--bg)) 12px); }
@media (prefers-reduced-motion: reduce) {
  .spinner { animation-name: star-tint; }
}
.spinner-wrap { text-align: center; padding: 80px 16px; }
.spinner-label {
  color: var(--ink-soft); margin-top: 10px;
  font-family: var(--font-label); font-weight: 700; font-size: var(--fs-tag);
  text-transform: uppercase; letter-spacing: .5px;
}
@keyframes spin { to { transform: rotate(360deg); } }
/* The star turns through the five brand colours. */
@keyframes star-turn {
  0%          { transform: rotate(0);       background: var(--butter-s); }
  15%, 20%    { transform: rotate(180deg);  background: var(--pink-s); }
  35%, 40%    { transform: rotate(360deg);  background: var(--lav-s); }
  55%, 60%    { transform: rotate(540deg);  background: var(--mint-s); }
  75%, 80%    { transform: rotate(720deg);  background: var(--fog-s); }
  95%, 100%   { transform: rotate(900deg);  background: var(--butter-s); }
}
@keyframes star-tint {
  0%, 100% { background: var(--butter-s); }
  20%      { background: var(--pink-s); }
  40%      { background: var(--lav-s); }
  60%      { background: var(--mint-s); }
  80%      { background: var(--fog-s); }
}

/* ── Ex-tax price marker — every price is shown before tax, followed by this grey "+tax"
 * (STUDIO_CONFIG.CONSUMPTION_TAX); the amount charged is the price plus tax. ── */
.plus-tax {
  color: var(--ink-faint);
  font-size: 0.78em;
  font-weight: 400;
  margin-left: 3px;
  white-space: nowrap;
}

/* ── Accessibility helper ── */
.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;
}

/* ── Portrait lock — every screen is designed for a phone held upright; none
 * of them adapt to landscape. Keyed on a short viewport (a rotated phone),
 * not just orientation, so tablets and the desktop dev browser are unaffected. */
@media (orientation: landscape) and (max-height: 500px) {
  body > * { display: none !important; }
  body::before {
    content: "Please rotate your device back to portrait. This app is designed for portrait use only.";
    position: fixed;
    inset: 0;
    z-index: 999999;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: 40px;
    background: var(--bg);
    color: var(--ink-soft);
    font-family: var(--font-sans);
    font-size: var(--fs-body);
    line-height: var(--lh-body);
  }
}

/* ── Scrollbars: soft under a mouse, none on a touch screen ── */
@media (hover: hover) and (pointer: fine) {
  * { scrollbar-width: thin; scrollbar-color: var(--line) transparent; }
  *::-webkit-scrollbar { width: 8px; height: 8px; }
  *::-webkit-scrollbar-thumb { background: var(--line); border-radius: 8px; }
  *::-webkit-scrollbar-track { background: transparent; }
}
/* !important: a module's own `scrollbar-width: thin` would otherwise bring one back. */
@media (hover: none), (pointer: coarse) {
  * { scrollbar-width: none !important; }
  *::-webkit-scrollbar { display: none !important; }
}
