:root {
  color-scheme: light;
  /* The `siteColors` block in DESIGN.md is the canon.
     `tool/design-token-audit.mjs` fails if these drift from it. */
  --ink: #0f1415;
  --muted: #5e5e5e;
  --brand: #055eaa;
  --brand-dark: #044b87;
  --canvas: #ffffff;
  --surface: #ffffff;
  --line: #c6c6c6;
  --danger: #b42318;
}

* { box-sizing: border-box; }

[hidden] { display: none !important; }

/* Japanese line breaking. `strict` is what keeps 「ー」, small kana and
   repetition marks off the head of a line; `auto` leaves it to the browser and
   they land there. `word-break: normal` is stated rather than assumed, because
   `break-all` — the reflex fix for an overflowing box — turns all of this off.
   A long unbroken URL is handled where it appears, not by loosening the page. */
:lang(ja), body {
  line-break: strict;
  /* Two declarations of one property, on purpose: a browser that does not know
     `auto-phrase` keeps `normal`, and one that does breaks on phrase
     boundaries instead of mid-word — 匿／名 and アカウン／ト are what the
     default leaves behind. Never `break-all`, which turns the prohibitions off
     entirely. */
  word-break: normal;
  word-break: auto-phrase;
}

/* Phrase-wrapped text. `/assets/ja-wrap.js` puts <wbr> at every boundary a
   line may break at (the same rules as the app's ja_text_wrapping.dart) and
   adds this class; `keep-all` then removes every other opportunity between
   Japanese characters. `anywhere` is the release valve for a run wider than
   the line at 320px and 200% text — it only acts when nothing else fits, and
   `line-break: strict` still holds underneath it.
   The descendants are named too: `:lang(ja)` above declares `auto-phrase` on
   every element, which would beat plain inheritance from the scope. */
.ja,
.ja * {
  word-break: keep-all;
  overflow-wrap: anywhere;
}
/* ja-wrap.js binds a character that may not start a line to the one before
   it (and one that may not end a line to the one after) in this span, so the
   `anywhere` valve above can never cut between them. */
.ja-glue { white-space: nowrap; }
/* Text a script writes after the page is wrapped (the deletion status line,
   a button whose label changes) has no <wbr> in it, and `keep-all` would make
   the whole sentence one unbreakable run for the `anywhere` valve to cut at
   random. Such elements carry `data-ja-skip` and go back to the browser's own
   rules: strict kinsoku, phrase breaking where supported. */
.ja [data-ja-skip],
.ja [data-ja-skip] * {
  word-break: normal;
  word-break: auto-phrase;
  overflow-wrap: anywhere;
}

/* =====================================================================
   Legacy pages (the operator console). They carry no body class, and every
   rule here is scoped to that so the public pages below can own their own
   layout without overriding it piece by piece. Kept as it was.
   ===================================================================== */

body:not(.site) {
  margin: 0;
  background: var(--canvas);
  color: var(--ink);
  font-family: -apple-system, BlinkMacSystemFont, "Hiragino Sans", "Yu Gothic UI", sans-serif;
  line-height: 1.75;
}

body:not(.site) a { color: var(--brand-dark); text-underline-offset: .18em; }
/* 3:1 against the canvas is the requirement for a non-text indicator.
   The amber this replaces sat at 2.01 and never met it. */
body:not(.site) a:focus-visible, body:not(.site) button:focus-visible, body:not(.site) input:focus-visible { outline: 3px solid #8a4b08; outline-offset: 3px; }

body:not(.site) > header, body:not(.site) > main, body:not(.site) > footer { width: min(100% - 2rem, 52rem); margin-inline: auto; }
body:not(.site) > header { display: flex; align-items: center; justify-content: space-between; padding-block: 1.25rem; }
/* The header mark is the app's own wordmark, drawn from the same outline
   (tool writes web/public/assets/wordmark.svg from lib/design_system/
   feed_wordmark.dart). Set in a typeface it was four letters that happened to
   spell the name; the app draws a shape, and a reader arriving from the app
   should meet the same shape. */
body:not(.site) a.brand { display: inline-flex; text-decoration: none; }
body:not(.site) a.brand img { display: block; width: auto; height: 1.7rem; }
body:not(.site) .brand { color: var(--brand); font-size: 1.35rem; font-weight: 850; letter-spacing: -.03em; text-decoration: none; }
body:not(.site) nav { display: flex; flex-wrap: wrap; gap: .8rem; font-size: .9rem; }
body:not(.site) main { padding-block: 3rem 5rem; }
body:not(.site) h1 { max-width: 18em; margin: 0 0 1rem; font-size: clamp(2rem, 7vw, 3.7rem); letter-spacing: -.045em; line-height: 1.15; }
body:not(.site) h2 { margin-top: 2.5rem; font-size: 1.35rem; line-height: 1.4; }
body:not(.site) p, body:not(.site) li { max-width: 46rem; }
body:not(.site) .lede { color: var(--muted); font-size: 1.08rem; }
/* Flat by default, as in the app: the 1px border carries the edge. */
body:not(.site) .card { margin-top: 1.5rem; padding: clamp(1.25rem, 4vw, 2rem); background: var(--surface); border: 1px solid var(--line); border-radius: 1.25rem; }
body:not(.site) .notice { padding: 1rem 1.2rem; border-left: .3rem solid var(--brand); background: #e5ecf5; }
body:not(.site) .danger { border-left-color: var(--danger); background: #faeaea; }
body:not(.site) label { display: block; margin-top: 1.15rem; font-weight: 700; }
body:not(.site) input { width: 100%; min-height: 3rem; margin-top: .4rem; padding: .7rem .8rem; border: 1px solid #767676; border-radius: .65rem; font: inherit; }
/* `overflow-wrap: anywhere` is the release valve for `word-break: auto-phrase`.
   Phrase breaking treats 「サインアウト」 as one unbreakable unit, so at a large
   default font size the label's minimum width exceeds the card and the row
   scrolls sideways. `anywhere` only takes effect when the label would otherwise
   overflow, and it still breaks under `line-break: strict`, so 禁則 holds. */
body:not(.site) button { min-height: 3rem; margin-top: 1rem; padding: .7rem 1.1rem; border: 0; border-radius: 999px; background: var(--brand); color: white; font: inherit; font-weight: 750; cursor: pointer; overflow-wrap: anywhere; }
body:not(.site) button:hover { background: var(--brand-dark); }
body:not(.site) button:disabled { opacity: .5; cursor: not-allowed; }
body:not(.site) .secondary { background: transparent; color: var(--brand-dark); border: 1px solid var(--brand); }
body:not(.site) .status { min-height: 1.75rem; margin-top: 1rem; font-weight: 650; }
body:not(.site) .muted { color: var(--muted); }
body:not(.site) .disclosure-list { margin: 0; }
body:not(.site) .disclosure-list div { display: grid; grid-template-columns: 7rem 1fr; gap: 1rem; padding-block: .8rem; border-top: 1px solid var(--line); }
body:not(.site) .disclosure-list div:first-child { border-top: 0; }
body:not(.site) .disclosure-list dt { font-weight: 750; }
body:not(.site) .disclosure-list dd { margin: 0; }
body:not(.site) select { width: 100%; min-height: 3rem; margin-top: .4rem; padding: .7rem .8rem; border: 1px solid #767676; border-radius: .65rem; background: var(--surface); font: inherit; }
body:not(.site) .request h3, body:not(.site) .empty h3 { margin-top: 0; }
body:not(.site) .empty { text-align: center; }
body:not(.site) .empty p { margin-inline: auto; }
body:not(.site) .request .kind { margin-block: .2rem 1rem; }
body:not(.site) .request .decisions { display: flex; flex-wrap: wrap; gap: .8rem; }

/* The unread mark. Its box holds two characters, so the padding is set in em
   and sized against them rather than at a flat one-character minimum, and the
   label never wraps. The tracking that separates 新 and 着 also lands after
   着, which would push the text left inside the box; `text-indent` puts back
   the same amount on the other side so the two margins read as equal. */
body:not(.site) .request .badge {
  display: inline-block;
  margin-inline-end: .5em;
  padding: .16em .7em;
  border-radius: .5em;
  background: var(--brand);
  color: #fff;
  font-size: .72em;
  font-weight: 700;
  letter-spacing: .08em;
  text-indent: .08em;
  white-space: nowrap;
  vertical-align: .1em;
}
body:not(.site) .request.fresh { border-color: var(--brand); }
body:not(.site) > footer { border-top: 1px solid var(--line); padding-block: 2rem 3rem; color: var(--muted); font-size: .9rem; }
body:not(.site) > footer nav { margin-top: .7rem; }
@media (max-width: 38rem) { body:not(.site) > header { align-items: flex-start; flex-direction: column; gap: .7rem; } body:not(.site) main { padding-top: 1.5rem; } body:not(.site) .disclosure-list div { grid-template-columns: 1fr; gap: .2rem; } }


/* =====================================================================
   Public pages (body.site): the landing page, the policies, support and
   the two utility pages. Laid out after the reference's own logged-out and
   legal pages; coloured and set from Feed's canon.
   ===================================================================== */

/* The canon above is light-only, and it is what these pages paint in light.
   Dark takes the app's own dark values (DESIGN.md `colors` and the neutral
   ramp at the dark tones), because the site has no dark canon of its own and
   a reader arriving from the app in dark should not be flashed with white. */
html:has(> body.site) { color-scheme: light dark; }

body.site {
  --s-canvas: var(--canvas);
  --s-ink: var(--ink);
  --s-muted: var(--muted);
  --s-line: var(--line);
  /* Text, and fills that carry text: Feed Blue Strong. */
  --s-brand: var(--brand);
  --s-on-brand: #ffffff;
  /* Shapes with no text on them: Feed Blue (DESIGN.md §2). */
  --s-fill: #2698f9;
  --s-danger: var(--danger);
  --s-focus: #8a4b08;
  /* feedNeutral(94) / (96): the input and notice fills. */
  --s-surface: #ebeeef;
  --s-surface-low: #f2f4f5;
  --s-hover: rgba(15, 20, 21, 0.04);
  --s-press: rgba(15, 20, 21, 0.08);
  --s-danger-wash: #faeaea;

  --s-bar-h: 3.5rem;
  /* The page gutter is px on purpose. DESIGN.md: 縦の余白は文字に合わせて
     伸ばすが、左右はページの余白16ptのままにする — at 200% text a 1rem gutter
     took 64px of a 320px screen away from the text it was framing. */
  --s-pad: 16px;
  --s-measure: 40em;

  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--s-canvas);
  color: var(--s-ink);
  font-family: -apple-system, BlinkMacSystemFont, "Hiragino Sans", "Hiragino Kaku Gothic ProN",
    "Noto Sans JP", "Yu Gothic UI", "Yu Gothic", Meiryo, Roboto, "Segoe UI", system-ui, sans-serif;
  font-size: 1rem;
  line-height: 1.8;
  /* Body text sits at 0 to 0.04em (kerning.md §2). Pair kerning on for Latin. */
  letter-spacing: 0.02em;
  font-kerning: normal;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

@media (prefers-color-scheme: dark) {
  body.site {
    --s-canvas: #0b0f15;   /* dark-canvas */
    --s-ink: #dee3e5;      /* feedNeutral(90) */
    --s-muted: #bbc7cf;    /* feedSecondaryInk, dark */
    --s-line: #434749;     /* feedNeutral(30) */
    --s-brand: #88c7fb;    /* feed-blue-light */
    --s-on-brand: #0b0f15;
    --s-fill: #88c7fb;
    --s-danger: #ffb4ab;   /* error-dark */
    --s-focus: #ffb86a;    /* warning-amber-dark */
    --s-surface: #1c2021;  /* feedNeutral(12) */
    --s-surface-low: #181c1d;
    --s-hover: rgba(222, 227, 229, 0.05);
    --s-press: rgba(222, 227, 229, 0.1);
    --s-danger-wash: #3a1d1a;
  }
}

.site ::selection { background: rgba(38, 152, 249, 0.25); }

/* Links, except the pills: a pill is a button that happens to navigate, and
   takes its colours from the pill rules below. */
.site a:not(.pill) { color: var(--s-brand); text-decoration-thickness: 1px; text-underline-offset: 0.2em; }
.site a:not(.pill):hover { text-decoration-thickness: 2px; }
.site a:focus-visible,
.site button:focus-visible,
.site input:focus-visible,
.site summary:focus-visible,
.site select:focus-visible {
  outline: 3px solid var(--s-focus);
  outline-offset: 3px;
  border-radius: 0.25em;
}

.site h1, .site h2, .site h3 {
  /* Headings: tighten the full-width punctuation and track in (kerning.md). */
  font-feature-settings: "palt" 1;
  font-weight: 800;
  color: var(--s-ink);
}

.skip {
  position: absolute;
  left: 1rem;
  top: -10rem;
  z-index: 10;
  padding: 0.75em 1em;
  background: var(--s-canvas);
  border: 1px solid var(--s-line);
  border-radius: 0.5em;
}
.skip:focus { top: 0.75rem; }

/* The wordmark is a mask over `currentColor`, so it takes the ink of the
   theme it is drawn in — the file's own fill is ignored. An <img> would stay
   black on the dark canvas. */
.wordmark {
  display: block;
  aspect-ratio: 2.72022;
  background-color: currentColor;
  -webkit-mask: url("/assets/wordmark.svg") center / contain no-repeat;
  mask: url("/assets/wordmark.svg") center / contain no-repeat;
  forced-color-adjust: none;
}

/* ---- top bar ---- */
.site-bar {
  border-bottom: 1px solid var(--s-line);
  background: var(--s-canvas);
}
.site-bar__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0 1rem;
  width: min(100% - 2 * var(--s-pad), 72rem);
  min-height: var(--s-bar-h);
  margin-inline: auto;
}
.site a.site-bar__brand {
  display: inline-flex;
  align-items: center;
  min-height: 3rem;
  color: var(--s-ink);
}
.site-bar__brand .wordmark { height: 1.625rem; }
.site-bar__nav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  margin-left: auto;
  gap: 0.25rem 1.25rem;
  font-size: 0.9375rem;
  letter-spacing: 0.01em;
}
.site-bar__nav a:not(.pill) {
  color: var(--s-ink);
  font-weight: 700;
  text-decoration: none;
  white-space: nowrap;
}
.site-bar__nav a:not(.pill):hover { text-decoration: underline; }
/* A four-character label is never split (ログイ／ン). When the bar cannot hold
   it beside the wordmark, the whole nav wraps onto a second row instead. */
.site-bar__nav .pill { white-space: nowrap; flex: none; }
/* The two text links leave the bar when it cannot hold them beside the
   wordmark and the login pill; the footer carries both. A container query in
   em, not a media query: its em is the bar's own text size, so a reader who
   enlarged the text loses the links at the width where they stop fitting,
   not at a width measured in default-size characters. */
.site-bar { container-type: inline-size; }
@container (max-width: 26em) {
  .site-bar__nav .site-bar__link { display: none; }
}

/* ---- buttons ----
   Pills, as the app's FeedPill (StadiumBorder). 48px is the floor for any
   operation (DESIGN.md), and the sides keep 24px, widening to one character
   only when the text is enlarged (yohaku.md's button exception). */
.pill,
.site button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  min-height: 3rem;
  margin: 0;
  padding: 0.5em max(24px, 1em);
  border: 1px solid transparent;
  border-radius: 9999px;
  background: var(--s-brand);
  color: var(--s-on-brand);
  font: inherit;
  font-size: 0.9375rem;
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: 0.01em;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  overflow-wrap: anywhere;
  -webkit-tap-highlight-color: transparent;
}
.pill:hover,
.site button:hover:not(:disabled) { background: color-mix(in srgb, var(--s-brand) 88%, #000); text-decoration: none; }
.pill:active,
.site button:active:not(:disabled) { background: color-mix(in srgb, var(--s-brand) 80%, #000); }
.pill--outline,
.site button.secondary {
  background: transparent;
  border-color: var(--s-line);
  color: var(--s-brand);
}
.pill--outline:hover,
.site button.secondary:hover:not(:disabled) { background: var(--s-hover); }
.pill--outline:active,
.site button.secondary:active:not(:disabled) { background: var(--s-press); }
.pill--block { width: min(100%, 20rem); }
.pill--small { min-height: 2.25rem; padding-inline: max(16px, 1em); font-size: 0.875rem; }
/* The small pill sits in the bar beside text links. Its visible fill is 36px,
   its target is the bar's 48px line: the padding below extends the hit area
   without growing the drawn pill. */
.pill--small { position: relative; }
.pill--small::after { content: ""; position: absolute; inset: -6px -4px; }
/* The one destructive confirmation. Red is used only here, and the words on
   the button and the notice above it say the same thing (Safety Colour Rule). */
.site button.danger { background: var(--s-danger); color: var(--s-on-brand); }
.site button.danger:hover:not(:disabled) { background: color-mix(in srgb, var(--s-danger) 88%, #000); }
@media (prefers-color-scheme: dark) {
  .site button.danger { color: #0b0f15; }
}
/* Disabled: the whole control at 40%, never swapped to grey (DESIGN.md). */
.site button:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* ---- footer ---- */
.site-footer {
  margin-top: auto;
  padding: 1.25rem var(--s-pad) 2rem;
  border-top: 1px solid var(--s-line);
  color: var(--s-muted);
  font-size: 0.8125rem;
  line-height: 1.6;
  letter-spacing: 0.04em;
  text-align: center;
}
.site-footer__links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.25rem 1rem;
  margin: 0 auto;
  padding: 0;
  max-width: 60rem;
  list-style: none;
}
.site .site-footer__links a {
  display: inline-block;
  max-width: 100%;
  padding-block: 0.35em;
  color: var(--s-muted);
  text-decoration: none;
  /* Breaks only at the <wbr> written between the two words of a compound
     (コミュニティ／ガイドライン, プライバシー／ポリシー), which is where a line
     has to break once 200% text no longer holds twelve characters. */
  word-break: keep-all;
  overflow-wrap: anywhere;
}
.site .site-footer__links a:hover { text-decoration: underline; }
.site-footer__links span { display: inline-block; padding-block: 0.35em; word-break: keep-all; }
.site-footer__note { margin: 0.75rem auto 0; }
.site-footer__copy { margin: 0.25rem auto 0; }

/* ---- document pages ---- */
.doc-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  width: min(100% - 2 * var(--s-pad), var(--s-measure));
  margin: 0 auto;
  padding-block: 2.5rem 4rem;
}
/* Two columns only when both fit at the reader's own text size: the query is
   in em, which the browser resolves against the default font size, so a
   reader who doubled it keeps one column instead of a squeezed text. */
@media (min-width: 68.75em) {
  .doc-layout--toc {
    grid-template-columns: 14rem minmax(0, var(--s-measure));
    column-gap: 4rem;
    width: min(100% - 2 * var(--s-pad), calc(14rem + 4rem + var(--s-measure)));
  }
}

.doc { min-width: 0; }
.doc > :first-child { margin-top: 0; }
.doc h1 {
  margin: 0 0 0.5rem;
  /* Titles are single compounds (プライバシーポリシー, コミュニティガイドライン)
     that must not be split (kaigyo.md §1). At 320px the full size does not
     hold twelve characters, so the size follows the viewport down to 1.5rem;
     the split is avoided by fitting, not by breaking inside the word. */
  font-size: clamp(1.5rem, 7.2vw, 2rem);
  line-height: 1.3;
  letter-spacing: -0.02em;
}
.doc h2 {
  margin: 2.75rem 0 0.75rem;
  font-size: 1.375rem;
  line-height: 1.45;
  letter-spacing: -0.01em;
  scroll-margin-top: 1.5rem;
}
.doc h3 {
  margin: 1.75rem 0 0.5rem;
  font-size: 1.0625rem;
  line-height: 1.5;
  letter-spacing: 0;
  font-weight: 700;
}
.doc p, .doc li, .doc dd { max-width: var(--s-measure); }
.doc p { margin: 0 0 1em; }
.doc ul, .doc ol { margin: 0 0 1em; padding-left: 1.25em; }
.doc li { margin-bottom: 0.5em; }
.doc li::marker { color: var(--s-muted); }
.doc strong { font-weight: 700; }
.doc-meta {
  margin: 0 0 2rem;
  color: var(--s-muted);
  font-size: 0.875rem;
  letter-spacing: 0.02em;
}
/* The closing line of a page (退会ページの問い合わせ先). */
.doc > .doc-meta:last-child { margin: 2rem 0 0; }
.lede {
  margin: 0 0 2rem;
  color: var(--s-muted);
  font-size: 1.0625rem;
  line-height: 1.75;
}
.muted { color: var(--s-muted); }

/* A numbered heading (「1. 取得する情報」). The title is one inline block, so
   when the line cannot hold both, the number stands alone and the title moves
   down whole, instead of the last word of the title (情報) being left on a
   line of its own. Markup only; the words are unchanged. */
.doc h2 .h-title { display: inline-block; }

/* A section inside a document, separated by a rule rather than boxed: the
   rule and the heading already say where it starts (DESIGN.md: Spacing
   Before Surface). */
.doc-section {
  margin-top: 2.5rem;
  padding-top: 0.25rem;
  border-top: 1px solid var(--s-line);
}
.doc-section > h2 { margin-top: 1.5rem; }

/* Definition rows (外部送信, 運営者情報). */
.facts { margin: 0 0 1.25rem; container-type: inline-size; }
.facts > div {
  display: grid;
  grid-template-columns: 8em minmax(0, 1fr);
  gap: 0.25rem 1.25rem;
  padding-block: 0.75rem;
  border-top: 1px solid var(--s-line);
}
.facts > div:last-child { border-bottom: 1px solid var(--s-line); }
.facts dt { font-weight: 700; }
.facts dd { margin: 0; }
/* One column when the value column would hold fewer than about twenty
   characters. A container query, so enlarged text reaches it too. */
@container (max-width: 30em) {
  .facts > div { grid-template-columns: minmax(0, 1fr); }
}

/* A short notice: one to three lines, so 1.25 characters of inset (yohaku.md
   §3), with the vertical inset trimmed by half the leading (§4). The outer
   margin is kept at least the inner one (§5). */
.callout {
  --pad: 1.25em;
  --lh: 1.75;
  margin: 1.5em 0;
  padding: calc(var(--pad) - (var(--lh) - 1) * 0.5em) var(--pad);
  border-radius: 1rem;
  background: var(--s-surface);
  line-height: var(--lh);
}
.callout > :last-child { margin-bottom: 0; }
.callout--passage { --pad: 1.5em; }
/* The Safety Colour Rule: the red is never the only signal. The mark and the
   words carry it too. */
.callout--danger {
  display: flex;
  gap: 0.6em;
  align-items: flex-start;
  background: var(--s-danger-wash);
  color: var(--s-danger);
  font-weight: 700;
}
.callout--danger::before {
  content: "";
  flex: none;
  width: 1.15em;
  height: 1.15em;
  margin-top: calc((var(--lh) * 1em - 1.15em) / 2);
  background-color: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2.5 1.5 21h21L12 2.5Zm-1.2 7h2.4l-.3 6h-1.8l-.3-6Zm1.2 7.6a1.3 1.3 0 1 1 0 2.6 1.3 1.3 0 0 1 0-2.6Z'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2.5 1.5 21h21L12 2.5Zm-1.2 7h2.4l-.3 6h-1.8l-.3-6Zm1.2 7.6a1.3 1.3 0 1 1 0 2.6 1.3 1.3 0 0 1 0-2.6Z'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* ---- table of contents ---- */
.toc {
  margin: 0 0 2rem;
  font-size: 0.9375rem;
  line-height: 1.5;
  letter-spacing: 0.01em;
}
.toc summary {
  display: flex;
  align-items: center;
  min-height: 3rem;
  padding: 0 1em;
  border: 1px solid var(--s-line);
  border-radius: 9999px;
  font-weight: 700;
  cursor: pointer;
  list-style: none;
}
.toc summary::-webkit-details-marker { display: none; }
.toc summary::after {
  content: "";
  width: 0.5em;
  height: 0.5em;
  margin-left: auto;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: translateY(-25%) rotate(45deg);
}
.toc[open] summary::after { transform: translateY(15%) rotate(-135deg); }
.toc ol {
  margin: 0.75rem 0 0;
  padding: 0;
  list-style: none;
  border-left: 1px solid var(--s-line);
}
.site .toc a {
  display: block;
  padding: 0.45em 0 0.45em 1em;
  margin-left: -1px;
  border-left: 3px solid transparent;
  color: var(--s-muted);
  text-decoration: none;
}
.site .toc a:hover { color: var(--s-ink); }
.site .toc a[aria-current="true"] {
  border-left-color: var(--s-fill);
  color: var(--s-ink);
  font-weight: 700;
}
@media (min-width: 68.75em) {
  .toc {
    position: sticky;
    top: 1.5rem;
    align-self: start;
    max-height: calc(100vh - 3rem);
    overflow: auto;
    margin: 0;
  }
  .toc summary { display: none; }
  .toc ol { margin-top: 0; }
}

/* ---- forms (退会, 確認) ---- */
.form-block {
  margin: 2rem 0 0;
  padding-top: 0.25rem;
  border-top: 1px solid var(--s-line);
}
.form-block > h2 { margin-top: 1.5rem; }
.site label {
  display: block;
  margin: 1.25rem 0 0.4rem;
  font-weight: 700;
  font-size: 0.9375rem;
  letter-spacing: 0.01em;
}
/* Filled, not outlined: the app's inputs are surfaceContainer with a 16px
   corner and one character of inset, and focus draws a 2px Feed Blue edge —
   a shape, so the fill blue rather than the text blue (DESIGN.md §5). */
.site input[type="text"],
.site input[type="email"],
.site input:not([type]) {
  display: block;
  width: 100%;
  min-height: 3rem;
  padding: 0.6em 1em;
  border: 2px solid transparent;
  border-radius: 1rem;
  background: var(--s-surface);
  color: var(--s-ink);
  font: inherit;
  letter-spacing: 0.02em;
}
.site input:focus { outline: none; border-color: var(--s-fill); }
.site input:focus-visible { outline: none; }
.form-actions { margin-top: 1rem; }

/* The status line under the deletion forms. The script paints its text in
   the light canon's red or blue inline; this band keeps a light ground under
   it in both themes so that ink stays readable, and keeps its link in the
   same ink. */
.site .status:not(:empty) {
  margin: 1.5rem 0 0;
  padding: 0.75em 1.25em;
  border-radius: 1rem;
  background: #ebeeef;
  color: #0f1415;
  font-weight: 700;
  line-height: 1.7;
}
.site .status a { color: #055eaa; }

/* =====================================================================
   Landing page
   ===================================================================== */

.lp-first {
  display: flex;
  flex-direction: column;
  min-height: 100svh;
}
.lp-hero {
  flex: 1;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-content: start;
  padding: 1.25rem var(--s-pad) 2.5rem;
}
.lp-hero__mark {
  color: var(--s-ink);
  padding-block: 0.25rem 0;
}
.lp-hero__mark .wordmark { height: 2.5rem; }
.lp-hero__panel { min-width: 0; }

/* The heading is set in three hand-made phrases (同じ大学の人にしか / 聞けないことを、
   / 匿名で。), each an inline block, so the lines are those three at every width
   rather than whatever the column cuts. Its size is capped by the column so
   the longest phrase (nine characters) fits one line — but never below
   1.5rem: a reader at 200% text keeps large type, and a phrase that no longer
   fits then breaks inside itself at its own phrase boundary (同じ大学の／人にしか)
   instead of the whole heading shrinking under the button below it. */
.lp-hero__title {
  --chars: 9.4;
  margin: 3rem 0 2.5rem;
  font-size: max(1.5rem, min(4rem, calc((100vw - 2 * var(--s-pad)) / var(--chars))));
  line-height: 1.28;
  letter-spacing: -0.03em;
  font-weight: 800;
}
.lp-hero__title .phrase,
.lp-hero__sub .phrase { display: inline-block; }
/* Shown instead of the sign-up and login controls where the web client is not
   open yet (site.js reads the deployment from /firebase-config.js). */
.lp-prelaunch { margin: 0; font-weight: 700; }
.lp-cta .lp-prelaunch { margin-top: 1.5rem; max-width: 26rem; }
.lp-hero__sub {
  /* Two hand-made phrases (参加には、 / 大学メールが必要です。), like the title:
     one line where the column holds sixteen characters, the two phrases as
     the two lines where it does not. */
  margin: 0 0 2rem;
  font-size: max(1.125rem, min(1.9375rem, calc((100vw - 2 * var(--s-pad)) / 11.6)));
  line-height: 1.35;
  letter-spacing: -0.02em;
}
.lp-actions {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  width: min(100%, 20rem);
}
.lp-note {
  margin: 0.75rem 0 0;
  color: var(--s-muted);
  font-size: 0.8125rem;
  line-height: 1.6;
  letter-spacing: 0.04em;
}
/* The three documents as separate links rather than a sentence: punctuation
   after a link cannot be glued to it across the element edge, and at 200%
   text the line broke between プライバシーポリシー and its 、. */
.lp-note-links {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 1rem;
  margin: 0.25rem 0 0;
  padding: 0;
  list-style: none;
  font-size: 0.8125rem;
  line-height: 1.6;
  letter-spacing: 0.04em;
}
.lp-note-links a { word-break: keep-all; overflow-wrap: anywhere; }
.lp-have {
  margin: 2.5rem 0 1.25rem;
  font-size: 1.0625rem;
  font-weight: 700;
  line-height: 1.4;
  letter-spacing: 0.01em;
}
.lp-unofficial {
  margin: 2rem 0 0;
  color: var(--s-muted);
  font-size: 0.8125rem;
  line-height: 1.6;
  letter-spacing: 0.04em;
}
.lp-more {
  align-self: center;
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  min-height: 3rem;
  margin-bottom: 0.5rem;
  padding-inline: 1em;
  color: var(--s-muted);
  font-size: 0.875rem;
  text-decoration: none;
}
.site a.lp-more { color: var(--s-muted); }
.lp-more::after {
  content: "";
  width: 0.45em;
  height: 0.45em;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: translateY(-20%) rotate(45deg);
}

@media (min-width: 62.5em) {
  .lp-hero {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    align-content: stretch;
    align-items: center;
    padding: 0;
  }
  .lp-hero__mark {
    display: flex;
    justify-content: center;
    align-items: center;
    padding: 2rem;
  }
  .lp-hero__mark .wordmark {
    width: min(62%, 28rem);
    height: auto;
  }
  .lp-hero__panel { padding: 2rem 2rem 2rem 1rem; max-width: 47.5rem; }
  .lp-hero__title {
    margin-top: 0;
    font-size: max(1.5rem, min(4rem, calc((50vw - 3rem) / var(--chars))));
  }
  .lp-hero__sub { font-size: max(1.125rem, min(1.9375rem, calc((50vw - 3rem) / 11.6))); }
}

/* Below the fold. One column at a reading measure, sections divided by a
   full-width rule, lists as rows rather than cards. */
.lp-section { border-top: 1px solid var(--s-line); }
.lp-inner {
  width: min(100% - 2 * var(--s-pad), var(--s-measure));
  margin: 0 auto;
  padding-block: 3.5rem;
}
.lp-section h2 {
  margin: 0 0 1rem;
  /* DESIGN.md `headline`: 24px, 800, -0.02em — the one strong heading of a
     screen, which each section is. At 200% text on a 320px screen it holds
     six characters a line, enough for every heading here to end on three. */
  font-size: 1.5rem;
  line-height: 1.33;
  line-height: 1.4;
  letter-spacing: -0.02em;
  scroll-margin-top: 1.5rem;
}
.lp-section h3 {
  margin: 0 0 0.25rem;
  font-size: 1.0625rem;
  line-height: 1.5;
  letter-spacing: 0;
  font-weight: 700;
}
.lp-section p { margin: 0 0 1em; }
.lp-section .lede { margin-bottom: 1.5rem; }

/* Rows with a filled mark on the left: the mark is a heading for the row,
   not a control, so it is filled (DESIGN.md List Rows) and drawn in Feed
   Blue — a shape, not text. */
.rows { margin: 0; padding: 0; list-style: none; container-type: inline-size; }
.rows > li {
  display: grid;
  grid-template-columns: 1.5rem minmax(0, 1fr);
  column-gap: 1rem;
  padding-block: 1rem;
  border-top: 1px solid var(--s-line);
}
.rows > li:last-child { border-bottom: 1px solid var(--s-line); }
.rows__mark {
  width: 1.5rem;
  height: 1.5rem;
  margin-top: 0.15rem;
  color: var(--s-fill);
}
.rows p { margin: 0; color: var(--s-muted); }
.rows strong { display: block; font-weight: 700; line-height: 1.6; }
/* Same break point as the steps: at 200% text on a phone the mark stands
   above its row instead of taking a column from the text. */
@container (max-width: 14em) {
  .rows > li { grid-template-columns: minmax(0, 1fr); row-gap: 0.25rem; }
}

/* Steps. The numeral is text, so it takes the text blue; its ring is a
   shape, so it takes the fill blue. */
.steps { margin: 0; padding: 0; list-style: none; counter-reset: step; container-type: inline-size; }
.steps > li {
  display: grid;
  grid-template-columns: 2.5rem minmax(0, 1fr);
  column-gap: 1rem;
  padding-block: 1rem;
  border-top: 1px solid var(--s-line);
  counter-increment: step;
}
.steps > li:last-child { border-bottom: 1px solid var(--s-line); }
.steps > li::before {
  content: counter(step);
  display: grid;
  place-items: center;
  width: 2.5rem;
  height: 2.5rem;
  border: 2px solid var(--s-fill);
  border-radius: 50%;
  color: var(--s-brand);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
  line-height: 1;
}
.steps p { margin: 0; color: var(--s-muted); }
/* When the text column beside the numeral would hold fewer than about ten
   characters (200% text on a phone), the numeral stands above its step
   instead of taking a third of the width from it. */
@container (max-width: 14em) {
  .steps > li { grid-template-columns: minmax(0, 1fr); row-gap: 0.5rem; }
}

/* A specimen of a timeline row, drawn with the app's own metrics (avatar,
   the 8px gap, 15px text at 1.38, the community line above). It is an
   illustration, not a control: nothing in it is focusable. */
.specimen {
  margin: 2rem 0 0;
  border: 1px solid var(--s-line);
  border-radius: 1rem;
  overflow: hidden;
  container-type: inline-size;
}
.specimen__label {
  margin: 0;
  padding: 0.5em 1rem;
  border-bottom: 1px solid var(--s-line);
  color: var(--s-muted);
  font-size: 0.75rem;
  letter-spacing: 0.04em;
}
.specimen__row {
  display: grid;
  grid-template-columns: 2.5rem minmax(0, 1fr);
  column-gap: 0.5rem;
  padding: 0.75rem 1rem 0.5rem;
  font-size: 0.9375rem;
  line-height: 1.38;
  letter-spacing: 0;
}
.specimen__context {
  grid-column: 2;
  grid-row: 1;
  margin-bottom: 0.25rem;
  color: var(--s-muted);
  font-size: 0.8125rem;
  font-weight: 700;
}
.specimen__avatar {
  grid-column: 1;
  grid-row: 2 / span 3;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 50%;
  background: #d8e8e2;
  overflow: hidden;
  position: relative;
}
.specimen__avatar::after {
  content: "";
  position: absolute;
  inset: 0;
  background: #4f7266;
  -webkit-mask: url("/assets/brand/specimen-figure.png") center / cover no-repeat;
  mask: url("/assets/brand/specimen-figure.png") center / cover no-repeat;
}
@media (prefers-color-scheme: dark) {
  .specimen__avatar { background: #223731; }
  .specimen__avatar::after { background: #9dc4b7; }
}
.specimen__byline { grid-column: 2; grid-row: 2; color: var(--s-muted); }
.specimen__byline b { color: var(--s-ink); font-weight: 700; }
.specimen__body { grid-column: 2; grid-row: 3; margin: 0.125rem 0 0; }
.specimen__metrics {
  grid-column: 2;
  grid-row: 4;
  display: flex;
  flex-wrap: wrap;
  column-gap: 0.75rem;
  margin: 0.5rem 0 0;
  padding: 0;
  list-style: none;
  color: var(--s-muted);
  font-size: 0.8125rem;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
}
.specimen__metrics li {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  flex: 1 0 auto;
  min-height: 2rem;
}
.specimen__metrics svg { width: 1.2rem; height: 1.2rem; flex: none; }
/* When the text column beside the figure would hold only a few characters
   (200% text on a phone), the row stacks: figure, then byline, then text, so
   キャンパス生活 is not cut in two and the body is not set four characters a
   line. The em is the specimen's own text size, so this follows the text. */
@container (max-width: 14em) {
  .specimen__row { grid-template-columns: minmax(0, 1fr); row-gap: 0.25rem; }
  .specimen__row > * { grid-column: 1; }
  .specimen__context { grid-row: 1; }
  .specimen__avatar { grid-row: 2; }
  .specimen__byline { grid-row: 3; }
  .specimen__body { grid-row: 4; }
  .specimen__metrics { grid-row: 5; }
}

/* A term that reads as one word even though the phrase rules would split it
   (SNSの|ID). Short runs only: a long one would overflow at 320px. */
.nowrap { white-space: nowrap; }

/* Telephone numbers are dialled, not read as prose, so they stay out of the
   phrase wrapper (data-ja-skip). They may break only after a hyphen — the
   markup puts <wbr> there, because the line-breaking rules never break a
   hyphen between digits — so 200% text on a 320px screen gets 0570-／064-／556
   rather than a sideways scroll. */
.tel { font-variant-numeric: tabular-nums; letter-spacing: 0; word-break: keep-all; overflow-wrap: normal; }

/* FAQ */
.faq { border-top: 1px solid var(--s-line); }
.faq:last-of-type { border-bottom: 1px solid var(--s-line); }
.faq summary {
  display: flex;
  align-items: center;
  gap: 0.75em;
  min-height: 3rem;
  padding-block: 0.75rem;
  font-weight: 700;
  line-height: 1.6;
  cursor: pointer;
  list-style: none;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: "";
  flex: none;
  width: 0.55em;
  height: 0.55em;
  margin-left: auto;
  margin-right: 0.25em;
  border-right: 2px solid var(--s-muted);
  border-bottom: 2px solid var(--s-muted);
  transform: translateY(-25%) rotate(45deg);
}
.faq[open] summary::after { transform: translateY(20%) rotate(-135deg); }
.faq summary:hover { color: var(--s-brand); }
.faq__body { padding: 0 0 1rem; }
.faq__body p { margin: 0 0 0.75em; color: var(--s-muted); }
.faq__body p:last-child { margin-bottom: 0; }

.lp-cta { text-align: left; }
.lp-cta__note { margin: 1.5rem 0 0; }
.lp-cta__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: 1.5rem;
}

/* ---- 404 ---- */
.state {
  width: min(100% - 2 * var(--s-pad), 32rem);
  margin: 0 auto;
  padding-block: 5rem 4rem;
}
.state h1 {
  margin: 0 0 0.5rem;
  font-size: 1.9375rem;
  line-height: 1.35;
  letter-spacing: -0.02em;
}
.state p { margin: 0 0 1.75rem; color: var(--s-muted); }

@media (prefers-reduced-motion: reduce) {
  .site * { scroll-behavior: auto !important; transition: none !important; }
}
@media (prefers-reduced-motion: no-preference) {
  html:has(> body.site) { scroll-behavior: smooth; }
}

@media print {
  .site-bar, .site-footer, .toc, .skip { display: none; }
  body.site { color: #000; background: #fff; }
}
