/* 婚禮工作台 · 紙感設計系統（shared/paper.css）
   順序：tokens → base → components。字體 @font-face 在 fonts.css（build-fonts.sh 產生）。
   字體與顏色只在 :root 定義；元件一律引用變數。

   Components (class → one line):
   .sr-only         visually hidden text, still read by screen readers
   .num             tabular lining serif numerals
   .label           small grey caption label
   .lead            intro paragraph in secondary ink
   .i               20px stroke icon base (inline SVG)
   .brand           brand link row (wordmark + sub)
   .wordmark        brand wordmark, Dela Gothic One
   .brand-sub       small sub line under the wordmark
   .btn             base button (44px tap target)
   .btn-primary     primary action, crimson
   .btn-ghost       text-only button
   .btn-sm          compact button, still 44px tall
   .btn-row         full-width button for stacked mobile actions
   .icon-btn        44px square icon-only button; .plain adds hairline border
   .chips           wrapping row of filter chips
   .chip            filter chip; [aria-pressed="true"] = on
   .tag             status tag base
   .tag-today       status: today (crimson tint)
   .tag-soon        status: soon (amber tint)
   .tag-done        status: done (muted)
   .tag-pending     pending confirmation, double-rule stamp
   .pend-stamp      alias of .tag-pending for inline use
   .form-field      wrapper that stacks label, control, hint and error (use around .field-label + .field)
   .field-label     label wrapper that stacks a caption above a control
   .field           text input, select, textarea
   .field-hint      helper text under a control
   .field-error     error text under a control; pair with aria-invalid="true" on the control
   .check           checkbox row with its label (native control, accent colour)
   .switch          on/off switch row: label > input[type=checkbox][role=switch] + .switch-track + text
   .seg             segmented choice; .seg-opt[aria-pressed="true"] = chosen; set --seg-n (count) and --seg-i (chosen index)
   .card            paper card (white paper, fibre texture, paper shadow)
   .paper-stack     card with an offset sheet underneath
   .table-wrap      scroll wrapper and paper surface around a ledger table
   .ledger          data table; .responsive turns rows into cards below 700px
   .amt             right-aligned serif amount cell in a ledger
   .tabs            folder tabs; aria-current="page" or aria-selected="true" = active
   .sec             section wrapper (vertical rhythm)
   .sec-head        numbered section heading with gold double rule
   .sec-no          section number, e.g. 01
   .dialog          native <dialog> sheet; .dialog-actions aligns buttons right
   .toast           transient status line; .is-error for failures
   .empty           empty state panel with dashed edge
*/

/* ---------- 1. Tokens ---------- */
:root {
  /* Layers, back to front: chrome (navigation, recessed) → desk (content background) → paper cards
     (--shadow-paper) → raised hero/focus cards (--shadow-raised) → floating sheets (--shadow-float).
     --panel is the AI tool layer beside the content. */
  --chrome: #ECE6DC;
  --desk: #F6F3EE;
  --desk-line: #DAD3C7;
  --tab-off: #EAE5DC;
  --panel: #FBFAF7;
  --paper: #FFFFFF;
  --paper-2: #F6F3EE;
  --paper-edge: #E2DDD4;
  --card: #FFFFFF;

  --line: #E2DDD4;
  --line-strong: #CFC8BC;
  --field-line: #8F887D;
  --gold: #B79B6B;

  --ink: #1B1A18;
  --ink-2: #66625B;
  --focus: #1B1A18;

  --primary: #8C2F3D;
  --primary-hover: #74262F;
  --on-primary: #FFFFFF;

  --danger: #B3261E;
  --danger-hover: #8F1D17;
  --on-danger: #FFFFFF;

  --accent: #8C2F3D;
  --accent-text: #8C2F3D;
  --accent-hover: #74262F;
  --accent-tint: #F2E2DE;
  --accent-line: #D2A8A1;
  --on-accent: #FFFFFF;

  --remind: #E2C25E;
  --remind-tint: #FAF1D2;

  --pending-ink: #76582F;
  --pending-line: #8A6A3E;

  --scrim: rgba(27, 26, 24, 0.45);

  --tex-fiber: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='f'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .36 0 0 0 0 .34 0 0 0 0 .31 .08 0 0 0 -.018'/%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23f)'/%3E%3C/svg%3E");
  /* Light embossed paper behind everything (body, side menu, AI panel): fractal noise as a height map, lit
     from the top left, kept as faint warm-ink shadows and white highlights on a stitched tile. Cards keep
     --tex-fiber. */
  --tex-desk: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='p' filterUnits='userSpaceOnUse' x='0' y='0' width='240' height='240' color-interpolation-filters='sRGB'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.27' numOctaves='3' seed='7' stitchTiles='stitch'/%3E%3CfeDiffuseLighting lighting-color='white' surfaceScale='1' result='l'%3E%3CfeDistantLight azimuth='225' elevation='58'/%3E%3C/feDiffuseLighting%3E%3CfeColorMatrix in='l' result='s' values='0 0 0 0 .106 0 0 0 0 .102 0 0 0 0 .094 -0.18 0 0 0 0.153'/%3E%3CfeColorMatrix in='l' result='h' values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0.35 0 0 0 -0.297'/%3E%3CfeMerge%3E%3CfeMergeNode in='s'/%3E%3CfeMergeNode in='h'/%3E%3C/feMerge%3E%3C/filter%3E%3Crect width='240' height='240' filter='url(%23p)'/%3E%3C/svg%3E");

  --f-serif: "GenWanMin TW", "Songti TC", "PMingLiU", serif;
  --f-sans: "GenYoGothic TW", "PingFang TC", "Microsoft JhengHei", sans-serif;
  --f-brand: "Dela Gothic One", "GenWanMin TW", serif;

  --s-1: 4px;
  --s-2: 8px;
  --s-3: 12px;
  --s-4: 16px;
  --s-5: 24px;
  --s-6: 32px;
  --s-7: 48px;
  --s-8: 64px;
  --r: 3px;
  --tap: 44px;
  --fs-xs: 12px;
  --fs-sm: 14px;
  --fs-body-sm: 15px; /* dense reading text in narrow columns (AI replies) */
  --fs-md: 16px;
  --fs-lg: 20px;
  --fs-xl: 28px;
  --fs-2xl: 34px;

  --shadow-paper: 0 1px 1px rgba(27, 26, 24, 0.05), 0 10px 18px -14px rgba(27, 26, 24, 0.35);
  --shadow-raised: 0 1px 2px rgba(27, 26, 24, 0.07), 0 18px 32px -16px rgba(27, 26, 24, 0.38);
  --shadow-band: 0 8px 14px -12px rgba(27, 26, 24, 0.3);
  --shadow-side: -10px 0 24px -18px rgba(27, 26, 24, 0.35);
  --shadow-float: 0 14px 30px -6px rgba(27, 26, 24, 0.25), 0 2px 0 rgba(27, 26, 24, 0.06);
  --shadow-knob: 0 1px 2px rgba(27, 26, 24, 0.3);
}

/* ---------- 2. Base ---------- */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  min-height: 100vh;
  background-color: var(--desk);
  background-image: var(--tex-desk);
  color: var(--ink);
  font-family: var(--f-sans);
  font-size: var(--fs-md);
  line-height: 1.6;
}

img,
svg {
  display: block;
  max-width: 100%;
}

a {
  color: var(--accent-text);
  text-underline-offset: 3px;
}

a:hover {
  color: var(--accent-hover);
}

:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

h1,
h2,
h3 {
  font-family: var(--f-serif);
  font-weight: 600;
  line-height: 1.3;
  margin: 0;
}

h1 {
  font-size: var(--fs-2xl);
}

h2 {
  font-size: var(--fs-xl);
}

h3 {
  font-size: var(--fs-lg);
}

p {
  margin: 0;
}

button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
}

button {
  cursor: pointer;
}

.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;
}

.num {
  font-family: var(--f-serif);
  font-weight: 400;
  font-variant-numeric: lining-nums tabular-nums;
}

.label {
  font-size: var(--fs-xs);
  font-weight: 500;
  color: var(--ink-2);
  letter-spacing: 0.04em;
}

.lead {
  color: var(--ink-2);
  font-size: var(--fs-md);
}

.i {
  flex: none;
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ---------- 3. Brand ---------- */
.brand {
  display: inline-flex;
  align-items: center;
  gap: var(--s-3);
  min-height: var(--tap);
  color: var(--ink);
  text-decoration: none;
}

.brand:hover {
  color: var(--ink);
}

.wordmark {
  font-family: var(--f-brand);
  font-weight: 400;
  font-size: 30px;
  line-height: 1;
  letter-spacing: 0.02em;
  color: var(--ink);
}

.brand-sub {
  font-size: var(--fs-sm);
  color: var(--ink-2);
  letter-spacing: 0.08em;
}

/* ---------- 4. Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  min-height: var(--tap);
  padding: 0 var(--s-4);
  border-radius: var(--r);
  border: 1px solid var(--field-line);
  background: var(--card);
  color: var(--ink);
  text-decoration: none;
  font-size: var(--fs-sm);
  font-weight: 500;
  white-space: nowrap;
  transition: background-color 0.15s, border-color 0.15s, color 0.15s;
}

.btn:hover {
  background: var(--paper-2);
  color: var(--ink);
}

.btn:disabled {
  background: var(--paper-2);
  border-color: var(--line-strong);
  color: var(--ink-2);
  cursor: not-allowed;
}

.btn-primary {
  background: var(--primary);
  border-color: var(--primary);
  color: var(--on-primary);
}

.btn-primary:hover {
  background: var(--primary-hover);
  border-color: var(--primary-hover);
  color: var(--on-primary);
}

.btn-ghost {
  background: transparent;
  border-color: transparent;
  color: var(--ink-2);
}

/* After .btn:disabled in the cascade, so a disabled ghost fades out instead of looking like a filled button. */
.btn-ghost:disabled {
  background: transparent;
  border-color: transparent;
  opacity: 0.4;
}

/* Destructive confirm (delete). Filled like .btn-primary but in a red the brand burgundy is not. */
.btn-danger {
  background: var(--danger);
  border-color: var(--danger);
  color: var(--on-danger);
}

.btn-danger:hover {
  background: var(--danger-hover);
  border-color: var(--danger-hover);
  color: var(--on-danger);
}

/* Quiet destructive action (a delete button that opens a confirm dialog): red text, no fill. */
.btn-danger-text {
  background: transparent;
  border-color: transparent;
  color: var(--danger);
}

.btn-danger-text:hover {
  background: var(--accent-tint);
  color: var(--danger-hover);
}

.btn-sm {
  padding: 0 var(--s-3);
}

.btn-row {
  width: 100%;
}

.icon-btn {
  width: var(--tap);
  height: var(--tap);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--r);
  border: 1px solid transparent;
  background: transparent;
  color: var(--ink-2);
  flex: none;
}

.icon-btn:hover {
  background: var(--paper-2);
  color: var(--ink);
}

.icon-btn.plain {
  border-color: var(--line);
}

/* ---------- 5. Chips & tags ---------- */
.chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
}

.chip {
  min-height: var(--tap);
  padding: 0 var(--s-4);
  border-radius: 999px;
  border: 1px solid var(--field-line);
  background: var(--card);
  color: var(--ink);
  font-size: var(--fs-sm);
  transition: background-color 0.15s, color 0.15s;
}

.chip[aria-pressed="true"] {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--paper);
}

.tag {
  display: inline-flex;
  align-items: center;
  justify-self: start;
  min-height: 24px;
  padding: 0 var(--s-2);
  font-size: var(--fs-xs);
  font-weight: 500;
  border-radius: 2px;
  background: var(--paper-2);
  color: var(--ink-2);
  border: 1px solid var(--line-strong);
  white-space: nowrap;
}

.tag-today {
  background: var(--accent-tint);
  border-color: var(--accent-line);
  color: var(--accent-text);
}

.tag-soon {
  background: var(--remind-tint);
  border-color: var(--remind);
  color: var(--pending-ink);
}

.tag-done {
  background: var(--paper-2);
  color: var(--ink-2);
}

.tag-pending,
.pend-stamp {
  display: inline-flex;
  align-items: center;
  padding: 0 var(--s-2);
  min-height: 24px;
  font-size: var(--fs-xs);
  font-weight: 500;
  color: var(--pending-ink);
  background: var(--paper);
  border: 3px double var(--pending-line);
  border-radius: 2px;
  justify-self: start;
  white-space: nowrap;
  vertical-align: middle;
}

/* ---------- 6. Form controls ---------- */
.form-field {
  display: grid;
  gap: var(--s-1);
  min-width: 0;
}

.field-label {
  display: grid;
  gap: var(--s-1);
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--ink);
}

.field {
  display: block;
  width: 100%;
  min-height: var(--tap);
  padding: var(--s-2) var(--s-3);
  background: var(--card);
  border: 1px solid var(--field-line);
  border-radius: var(--r);
  color: var(--ink);
}

textarea.field {
  min-height: 96px;
  resize: vertical;
}

.field::placeholder {
  color: var(--ink-2);
}

.field:disabled {
  background: var(--paper-2);
  color: var(--ink-2);
}

.field[aria-invalid="true"] {
  border-color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
}

.field-hint {
  font-size: var(--fs-xs);
  color: var(--ink-2);
}

.field-error {
  font-size: var(--fs-sm);
  color: var(--accent-text);
}

.check {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  min-height: var(--tap);
  font-size: var(--fs-sm);
  color: var(--ink);
}

.check input {
  width: 24px;
  height: 24px;
  margin: 0;
  accent-color: var(--accent);
}

/* Switch and segmented control are adapted from Uiverse.io (MIT; see shared/uiverse.LICENSE):
   switch ← The-Best-Codes/bright-rabbit-33, segmented ← andrew-demchenk0/stupid-seahorse-9. */
.switch {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  min-height: var(--tap);
  font-size: var(--fs-sm);
  color: var(--ink);
  cursor: pointer;
}

.switch input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  opacity: 0;
}

.switch-track {
  position: relative;
  flex: none;
  width: 52px;
  height: 30px;
  border-radius: 999px;
  background: var(--line-strong);
  box-shadow: inset 0 0 0 1px var(--field-line);
  transition: background-color 0.25s, box-shadow 0.25s;
}

.switch-track::before {
  content: "";
  position: absolute;
  top: 3px;
  left: 3px;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--paper);
  box-shadow: var(--shadow-knob);
  transition: transform 0.25s cubic-bezier(0.2, 0.8, 0.2, 1);
}

.switch input:checked + .switch-track {
  background: var(--primary);
  box-shadow: inset 0 0 0 1px var(--primary);
}

.switch input:checked + .switch-track::before {
  transform: translateX(22px);
}

.switch input:focus-visible + .switch-track {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

.switch input:disabled + .switch-track {
  opacity: 0.5;
}

.switch:has(input:disabled) {
  cursor: not-allowed;
}

.seg {
  position: relative;
  isolation: isolate;
  display: inline-grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  border: 1px solid var(--ink);
  border-radius: var(--r);
  background: var(--paper);
  box-shadow: 3px 3px 0 var(--ink);
}

/* The ink pill under the chosen option; it slides when --seg-i changes. */
.seg::before {
  content: "";
  position: absolute;
  z-index: -1;
  top: 0;
  bottom: 0;
  left: 0;
  width: calc(100% / var(--seg-n, 2));
  background: var(--ink);
  transform: translateX(calc(100% * var(--seg-i, 0)));
  transition: transform 0.25s cubic-bezier(0.2, 0.8, 0.2, 1);
}

.seg-opt {
  min-height: var(--tap);
  min-width: 5.5rem;
  padding: 0 var(--s-4);
  border: 0;
  border-radius: 0;
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: var(--fs-sm);
  cursor: pointer;
  transition: color 0.25s;
}

.seg-opt[aria-pressed="true"] {
  color: var(--paper);
  font-weight: 600;
}

.seg-opt:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: -5px;
}

/* ---------- 7. Paper surfaces ---------- */
.card {
  background-color: var(--paper);
  background-image: var(--tex-fiber);
  border: 1px solid var(--paper-edge);
  border-radius: var(--r);
  box-shadow: var(--shadow-paper);
  padding: var(--s-5);
  display: grid;
  gap: var(--s-3);
  align-content: start;
}

.paper-stack {
  position: relative;
  isolation: isolate;
}

.paper-stack::before {
  content: "";
  position: absolute;
  inset: 6px -8px -8px 8px;
  z-index: -1;
  background-color: var(--paper-2);
  border: 1px solid var(--paper-edge);
  border-radius: var(--r);
  box-shadow: var(--shadow-paper);
  opacity: 0.5;
}

.table-wrap {
  width: 100%;
  overflow-x: auto;
  background-color: var(--paper);
  background-image: var(--tex-fiber);
  border: 1px solid var(--paper-edge);
  border-radius: var(--r);
  box-shadow: var(--shadow-paper);
}

.empty {
  padding: var(--s-5);
  border: 1px dashed var(--field-line);
  border-radius: var(--r);
  color: var(--ink-2);
  text-align: center;
  background: var(--paper-2);
}

/* ---------- 8. Folder tabs ---------- */
.tabs {
  display: flex;
  gap: var(--s-1);
  overflow-x: auto;
  margin-top: var(--s-6);
  border-bottom: 1px solid var(--line-strong);
}

.tabs a,
.tabs button {
  flex: none;
  min-height: var(--tap);
  padding: 0 var(--s-5);
  display: inline-flex;
  align-items: center;
  background: var(--tab-off);
  border: 1px solid var(--line-strong);
  border-bottom: 0;
  border-radius: 8px 8px 0 0;
  color: var(--ink-2);
  text-decoration: none;
  margin-bottom: -1px;
  font-size: var(--fs-sm);
  white-space: nowrap;
}

.tabs a:hover,
.tabs button:hover {
  color: var(--ink);
}

.tabs [aria-current="page"],
.tabs [aria-selected="true"] {
  background: var(--desk);
  color: var(--ink);
  font-weight: 500;
  box-shadow: inset 0 3px 0 var(--accent);
}

/* ---------- 9. Sections ---------- */
.sec {
  display: grid;
  gap: var(--s-4);
}

.sec-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-2) var(--s-4);
  padding-bottom: var(--s-3);
  border-bottom: 3px double var(--gold);
}

/* Numbered head (<span class="sec-no"> + <h2> + optional meta): number left, title centred, meta right. */
.sec-head:has(> .sec-no) {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
}

.sec-head > .sec-no {
  justify-self: start;
}

.sec-head:has(> .sec-no) > :is(h1, h2, h3) {
  grid-column: 2;
  margin: 0;
  text-align: center;
  /* Section titles are signposts, not the focus: same title tier as card titles, well below the page title. */
  font-size: var(--fs-lg);
  letter-spacing: 0.06em;
}

.sec-head:has(> .sec-no) > :nth-child(3) {
  grid-column: 3;
  justify-self: end;
  text-align: right;
}

.sec-head .label {
  color: var(--ink-2);
}

.sec-no {
  font-family: var(--f-serif);
  font-size: var(--fs-sm);
  color: var(--accent-text);
  letter-spacing: 0.08em;
}

/* ---------- 10. Ledger ---------- */
.ledger {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-sm);
}

.ledger caption {
  text-align: left;
  padding: var(--s-3) var(--s-4) 0;
  color: var(--ink-2);
  font-size: var(--fs-xs);
}

.ledger th,
.ledger td {
  padding: var(--s-3) var(--s-4);
  text-align: left;
  vertical-align: middle;
  border-bottom: 1px solid var(--line);
}

.ledger thead th {
  background: var(--paper-2);
  color: var(--ink-2);
  font-weight: 500;
  font-size: var(--fs-xs);
  border-bottom: 2px solid var(--line-strong);
}

.ledger tbody tr:hover td {
  background: var(--paper-2);
}

.ledger tbody tr:last-child td {
  border-bottom: 0;
}

.ledger .amt {
  font-family: var(--f-serif);
  text-align: right;
  white-space: nowrap;
}

.ledger a {
  min-height: var(--tap);
  display: inline-flex;
  align-items: center;
}

/* 手機：表格變卡片（需 .ledger.responsive 與 td[data-label]） */
@media (max-width: 699px) {
  .ledger.responsive thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
  }

  .ledger.responsive,
  .ledger.responsive tbody,
  .ledger.responsive tr,
  .ledger.responsive td,
  .ledger.responsive th {
    display: block;
    width: 100%;
  }

  /* 篩選、搜尋用 hidden 藏列；上面的 display: block 會蓋過 hidden，要再藏一次 */
  .ledger.responsive tr[hidden] {
    display: none;
  }

  .ledger.responsive tr {
    padding: var(--s-3) var(--s-4);
    border-bottom: 1px solid var(--line);
  }

  .ledger.responsive tr:last-child {
    border-bottom: 0;
  }

  .ledger.responsive td,
  .ledger.responsive th {
    border: 0;
    padding: var(--s-1) 0;
  }

  .ledger.responsive td[data-label]::before {
    content: attr(data-label);
    display: block;
    font-size: var(--fs-xs);
    color: var(--ink-2);
    font-weight: 500;
  }

  .ledger.responsive .amt {
    text-align: left;
  }
}

/* ---------- 11. Dialog & toast ---------- */
.dialog {
  width: min(440px, calc(100vw - 2 * var(--s-4)));
  max-height: calc(100vh - 2 * var(--s-5));
  max-height: calc(100dvh - 2 * var(--s-5));
  padding: var(--s-5);
  overflow-y: auto;
  overscroll-behavior: contain;
  border: 1px solid var(--paper-edge);
  border-radius: var(--r);
  background-color: var(--paper);
  background-image: var(--tex-fiber);
  box-shadow: var(--shadow-float);
  color: var(--ink);
}

.dialog[open] {
  display: grid;
  gap: var(--s-4);
}

/* A grid item keeps its content's width unless told otherwise; a wide child would push the buttons out of the dialog. */
.dialog > *,
.dialog-form {
  min-width: 0;
}

.dialog::backdrop {
  background: var(--scrim);
}

/* The buttons stay at the bottom edge while the fields scroll, so a tall dialog on a phone never hides them.
   Sticky offsets are measured from the padding edge inward, so `bottom` and the negative margin both cancel the
   dialog's padding: the bar sits on the dialog's bottom edge, and its own padding puts the buttons back inside. */
.dialog-actions {
  position: sticky;
  bottom: calc(-1 * var(--s-5));
  z-index: 1;
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: var(--s-2);
  margin: 0 calc(-1 * var(--s-5)) calc(-1 * var(--s-5));
  padding: var(--s-3) var(--s-5) var(--s-4);
  border-top: 1px solid var(--line);
  background-color: var(--paper);
}

@media (max-width: 699px) {
  .dialog {
    padding: var(--s-4);
    max-height: calc(100vh - 2 * var(--s-3));
    max-height: calc(100dvh - 2 * var(--s-3));
  }

  .dialog-actions {
    bottom: calc(-1 * var(--s-4));
    margin: 0 calc(-1 * var(--s-4)) calc(-1 * var(--s-4));
    padding: var(--s-3) var(--s-4);
  }
}

.toast {
  position: fixed;
  left: 50%;
  bottom: var(--s-5);
  transform: translateX(-50%);
  z-index: 10;
  display: flex;
  align-items: center;
  gap: var(--s-3);
  min-height: var(--tap);
  max-width: calc(100vw - 2 * var(--s-4));
  padding: var(--s-2) var(--s-4);
  border-radius: var(--r);
  background: var(--ink);
  color: var(--paper);
  font-size: var(--fs-sm);
  box-shadow: var(--shadow-float);
}

.toast[hidden] {
  display: none;
}

.toast.is-error {
  background: var(--primary);
  color: var(--on-primary);
}

/* ---------- 12. Motion ---------- */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
  }
}
