/* Four Hundred Squares — StackEdit-style split: source on the left, genkou
   yoshi on the right. Every measurement on the paper derives from --cell,
   which app.js recomputes to fit the pane. */

:root{
  color-scheme:light dark;
  --bg:#efece4;
  --chrome:#fbfaf6;
  --line:#ddd8cc;
  --ink:#2c2823;
  --dim:#8a8378;
  --accent:#a8503a;

  --paper:#fdfbf3;
  --rule:#bb6047;          /* the reddish-brown ruling of real manuscript paper */
  --paper-ink:#22201c;

  /* 漢字レベル alerts. Saturated where --rule is muted, so a flagged glyph does
     not read as part of the ruling it sits inside — the two are close in hue
     because manuscript paper's brown simply is a red, and separating them by
     hue instead would have meant a color that belongs to neither the paper nor
     an alert. --alert-ui is the same signal on the app's chrome, which unlike
     the paper does invert, so it gets its own value in the dark block below. */
  --alert:#c62015;
  --alert-ui:#c62015;

  /* These stacks must land on a font with real vertical metrics. A generic
     serif/sans-serif fallback often resolves to a face with no CJK at all, and
     per-character fallback then picks one with no vertical support — which
     rotates the kana and pushes them out of their squares. Hiragino covers the
     iPad; the Noto/Source Han/IPA entries cover everywhere else. No Chinese
     families: they would render Chinese glyph forms for shared kanji. */
  --mincho:"Hiragino Mincho ProN","HiraMinProN-W3","Yu Mincho","YuMincho","Noto Serif CJK JP","Noto Serif JP","Source Han Serif JP",IPAMincho,"MS Mincho",serif;
  --gothic:"Hiragino Kaku Gothic ProN","HiraKakuProN-W3","Hiragino Sans","Yu Gothic","YuGothic","Noto Sans CJK JP","Noto Sans JP","Source Han Sans JP",IPAGothic,"MS Gothic",sans-serif;

  /* Emoji squares need the color font *first*. Per-character fallback stops at
     the first family in the stack that has a glyph for the codepoints, so a CJK
     face carrying regional-indicator letterforms will claim U+1F1E6..1F1FF
     before the emoji font is ever consulted — which is how one flag can come
     out right and the next as a box in the same run. */
  --emoji:"Apple Color Emoji","Segoe UI Emoji","Noto Color Emoji","Twemoji Mozilla","EmojiOne Color","Android Emoji",sans-serif;
}
@media (prefers-color-scheme:dark){
  :root{
    --bg:#161512;
    --chrome:#1e1d19;
    --line:#302e28;
    --ink:#e8e3d8;
    --dim:#918a7d;
    --accent:#c4664c;

    /* Paper stays paper-colored in the dark, just dimmed: an inverted sheet
       reads as a screen, and the ruling is the whole look. */
    --paper:#e8e2d3;
    --rule:#a5573f;
    --paper-ink:#22201c;

    /* The paper dims but stays paper, so its alert only deepens to hold contrast
       against the duller cream. The footer does invert, and #c62015 on the dark
       chrome is about 2.9:1 — under the floor for text that small — so the UI
       alert lightens instead of following the paper. */
    --alert:#a81a10;
    --alert-ui:#e8695c;
  }
}

*{box-sizing:border-box}
html,body{height:100%;margin:0}
body{
  display:flex;flex-direction:column;
  background:var(--bg);color:var(--ink);
  font-family:system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
  -webkit-text-size-adjust:100%;
}

/* ── top bar ─────────────────────────────────────────────────────────────── */
.bar{
  display:flex;flex-wrap:wrap;align-items:center;gap:.75rem 1rem;
  padding:max(env(safe-area-inset-top),.55rem) .9rem .55rem;
  background:var(--chrome);border-bottom:1px solid var(--line);
}
.bar h1{
  margin:0;font-size:1rem;font-weight:600;letter-spacing:-.01em;white-space:nowrap;
}
.bar h1 .ja{font-family:var(--mincho);color:var(--dim);font-weight:400;margin-left:.35rem}
.controls{display:flex;flex-wrap:wrap;align-items:center;gap:.5rem;margin-left:auto}

.seg{display:inline-flex;border:1px solid var(--line);border-radius:999px;overflow:hidden;background:var(--bg)}
.seg button{
  font:inherit;font-size:.8rem;line-height:1;cursor:pointer;
  padding:.42rem .7rem;border:0;background:transparent;color:var(--dim);
  -webkit-tap-highlight-color:transparent;
}
.seg button[aria-pressed="true"]{background:var(--accent);color:#fff}
.btn{
  font:inherit;font-size:.8rem;line-height:1;cursor:pointer;
  padding:.42rem .8rem;border-radius:999px;
  border:1px solid var(--line);background:var(--chrome);color:var(--ink);
  -webkit-tap-highlight-color:transparent;
}
.btn:active{background:var(--bg)}
.seg button:focus-visible,.btn:focus-visible,.pg:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

/* ── options popover ─────────────────────────────────────────────────────────
   A panel rather than more buttons in the bar: 禁則処理 needs a checkbox and a
   sub-option of its own, and the bar was already carrying two segmented
   controls and three buttons before either existed. */
.menu{position:relative}
.panel{
  position:absolute;top:calc(100% + .5rem);right:0;z-index:20;
  width:min(19rem,calc(100vw - 1.8rem));
  display:flex;flex-direction:column;gap:.7rem;
  padding:.85rem;border:1px solid var(--line);border-radius:.7rem;
  background:var(--chrome);box-shadow:0 6px 24px rgba(0,0,0,.18);
}
/* display:flex above outranks the UA sheet's [hidden]{display:none}, so the
   attribute has to be honored explicitly or the panel never closes. */
.panel[hidden]{display:none}
.panel hr{margin:0;border:0;border-top:1px solid var(--line)}
.opt{display:flex;gap:.55rem;align-items:flex-start;font-size:.82rem;cursor:pointer}
.opt input{margin:.15rem 0 0;accent-color:var(--accent);flex:0 0 auto}
.opt b{font-weight:600}
.opt small{display:block;color:var(--dim);font-size:.74rem;line-height:1.35;margin-top:.15rem}
.opt--sub{margin-left:1.4rem}
/* The one option that is a choice rather than a switch. Stacked, because a
   19rem popover cannot hold a two-line label and an eight-item select side by
   side without squeezing one of them, and full width because it is also the
   only control here a finger has to hit precisely. */
.opt--row{flex-direction:column;gap:.4rem}
/* The one segmented control that is not in the bar. Full width like the select
   below it, so the panel's two choices line up and both are a fat target. */
.seg--wide{display:flex;width:100%}
.seg--wide button{flex:1;padding-block:.5rem}
.opt--row select{
  font:inherit;font-size:.82rem;width:100%;
  padding:.4rem .5rem;border:1px solid var(--line);border-radius:.4rem;
  background:var(--bg);color:var(--ink);
}
.opt--row select:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.opt:has(input:disabled){opacity:.45;cursor:default}
.btn--wide{width:100%;padding-block:.5rem}

/* ── the manuscript list ─────────────────────────────────────────────────────
   A screen rather than a third column: the split pane already uses the whole
   width of the iPad this is written on. It replaces the panes, and the bar
   swaps its editor controls for the list's one button, so neither screen shows
   a control belonging to the other. The footer stays: it carries the hint slot,
   which is where a failed write is reported, and a delete is exactly when that
   matters. */
body:not(.screen-list) #list-controls,
body.screen-list #editor-controls,
body.screen-list #panes{display:none}
#doclist-screen{flex:1;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch}

.doclist{
  list-style:none;margin:0 auto;padding:.6rem .9rem max(env(safe-area-inset-bottom),.9rem);
  max-width:46rem;
}
.doc{
  display:flex;align-items:stretch;gap:.3rem;
  border-bottom:1px solid var(--line);
}
/* The row is the target — a title is a tap away, not a tap *at*. */
.doc-open{
  flex:1;min-width:0;text-align:left;
  font:inherit;cursor:pointer;background:transparent;border:0;color:inherit;
  padding:.7rem .2rem;border-radius:.4rem;
  -webkit-tap-highlight-color:transparent;
}
.doc-open:active{background:var(--chrome)}
.doc-title{
  display:block;font-size:.95rem;line-height:1.4;
  /* Truncation is the browser's job: the ellipsis then lands where the row
     actually runs out, at whatever width the iPad is held. */
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.doc-title.untitled{color:var(--dim)}
.doc-meta{
  display:block;margin-top:.2rem;margin-left:.85rem;
  font-size:.76rem;color:var(--dim);font-variant-numeric:tabular-nums;
}
/* The open document, marked rather than hidden — it is still a row you can tap
   back into after wandering the list. Every row reserves the marker's width,
   including the rows that do not have one, so titles down the list share an
   edge; .85rem is that reservation, which is why the meta line matches it. */
.doc-title::before{
  content:"";display:inline-block;vertical-align:middle;
  width:.4rem;height:.4rem;margin-right:.45rem;border-radius:999px;background:transparent;
}
.doc[aria-current="true"] .doc-title{font-weight:600}
.doc[aria-current="true"] .doc-title::before{background:var(--accent)}
.doc-del{
  flex:0 0 auto;align-self:center;
  font:inherit;font-size:1.1rem;line-height:1;cursor:pointer;
  width:2.2rem;height:2.2rem;border-radius:999px;
  border:0;background:transparent;color:var(--dim);
  -webkit-tap-highlight-color:transparent;
}
.doc-del:active{background:var(--chrome);color:var(--alert-ui)}
.doc-open:focus-visible,.doc-del:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}

/* ── panes ───────────────────────────────────────────────────────────────── */
#panes{flex:1;min-height:0;display:flex}
.pane{display:flex;flex-direction:column;min-width:0;min-height:0}
.pane--text{flex:0 0 38%;border-right:1px solid var(--line);background:var(--chrome)}
.pane--paper{flex:1}

body.view-text .pane--paper,
body.view-paper .pane--text{display:none}
body.view-text .pane--text{flex:1;border-right:0}

@media (max-width:760px){
  #panes{flex-direction:column}
  .pane--text{flex:0 0 40%;border-right:0;border-bottom:1px solid var(--line)}
}

#src{
  flex:1;width:100%;min-height:0;resize:none;
  padding:.9rem 1rem;border:0;outline:none;
  background:transparent;color:var(--ink);
  font-family:var(--gothic);
  font-size:16px;             /* 16px keeps iOS Safari from zooming on focus */
  line-height:1.85;
}
#src::placeholder{color:var(--dim)}

/* ── the sheet ───────────────────────────────────────────────────────────── */
.paperwrap{
  flex:1;min-height:0;display:grid;place-items:center;
  padding:10px;overflow:hidden;touch-action:pan-y;
}
.sheet{
  display:flex;flex-direction:row-reverse;align-items:flex-start;
  gap:var(--gap);padding:var(--pad);
  background:var(--paper);border:1px solid var(--rule);
  box-shadow:0 3px 14px rgba(0,0,0,.13);
}
.colwrap{display:flex;flex-direction:column;width:var(--cell)}
.col{
  display:flex;flex-direction:column;
  width:100%;border:1px solid var(--rule);
}
/* ぶら下げ: the square-sized space below the ruling where a 、。 that would have
   opened the next column is written instead — literally hanging, outside the
   grid. Keeping it out there is the point: the character it follows stays full
   size in its own square, and the grid gives up nothing to make room. Its
   height is also the paper's wider bottom margin when nothing is hanging, which
   is how real 原稿用紙 is proportioned anyway. */
.hangslot{height:var(--cell);display:grid;place-items:center;overflow:hidden}
.sq{
  height:var(--cell);border-bottom:1px solid var(--rule);
  display:grid;place-items:center;overflow:hidden;
}
.col .sq:last-child{border-bottom:0}
/* One character per square, set vertically: writing-mode is what gets the
   vertical forms — ー「」、。 and the small kana all sit where vertical
   Japanese puts them, without any per-character special casing. */
.g{
  writing-mode:vertical-rl;text-orientation:mixed;
  font-size:calc(var(--cell) * .82);line-height:1;
  color:var(--paper-ink);
}
.g.above{color:var(--alert)}   /* 漢字 above the chosen 学年別漢字配当表 level */
body.font-mincho .g{font-family:var(--mincho)}
body.font-gothic .g{font-family:var(--gothic)}

/* Emoji get set horizontally. They have no vertical forms, so vertical mode
   buys nothing — and under text-orientation:mixed it actively hurts: every
   character whose Unicode Vertical_Orientation is R gets rotated 90°, which is
   exactly the emoji whose base codepoint lives outside the astral emoji blocks
   (keycaps, ✂️☔️❤️☺️, 🩷🪨). Some of those then clip, because a rotated glyph
   wider than it is tall overflows a square that is overflow:hidden.

   text-orientation:upright is the fix that looks obvious and is wrong: CSS
   Writing Modes forces font-variant-ligatures:none in that mode, and a flag
   emoji IS a ligature of two regional indicators. It would straighten the
   emoji and break every flag. Dropping to horizontal-tb touches neither.

   Slightly smaller than a CJK glyph, because an emoji fills its em box where a
   kanji sits inside one — at the same size it would crowd the ruling. */
.g.emoji{writing-mode:horizontal-tb;font-size:calc(var(--cell) * .76)}

/* A 。」 pair shares one square — at full size, because neither glyph needs the
   room a full character needs. The fix is placement, not size: give each its own
   box, overlap the boxes, and drop only the advance between them.

   Measured on the vertical forms (IPAGothic, ink as a fraction of a square with
   the em box centered in it): 。 draws top *right*, x .65–.87 by y .13–.35, and
   」 draws top *left*, x .13–.72 by y .17–.39. Both sit at the head of their own
   box — not at opposite ends of it — so stacking them head-to-foot would pile
   both into the top half. Hence a diagonal: 。 anchored to the head of the
   square, 」 half an em lower, which lands it bottom-left. Which is also how the
   pair is written by hand. Measured in place, that leaves the two inks a clear
   fifth of a square apart, both unshrunk.

   The offset is in em rather than a fraction of the square, so it tracks the
   glyphs rather than the ruling. It assumes the vertical form of a closing
   bracket draws at the head of its em box, which is the whole point of the
   substitution and holds in every face worth naming — and the square clips, so
   a face that disagreed would look wrong rather than break the grid.

   text-spacing-trim is the property that will say all this directly one day.
   Anchoring two boxes gets the same result on today's Safari, and unlike vpal
   it does not depend on the font carrying the feature. */
.g.pair{position:relative;width:100%;height:100%;writing-mode:horizontal-tb}
.g.pair span{
  position:absolute;left:50%;transform:translateX(-50%);
  writing-mode:vertical-rl;text-orientation:mixed;line-height:1;
}
.g.pair span:first-child{top:0}      /* 。 — top right */
.g.pair span:last-child{top:.5em}    /* 」 — half an em down, so bottom left */
body.font-mincho .g.emoji,
body.font-gothic .g.emoji{font-family:var(--emoji)}

/* The middle band of real manuscript paper: fish-tail mark, sheet number. */
.gutter{
  width:var(--gutter);height:calc(var(--cell) * 20);
  display:flex;flex-direction:column;align-items:center;
  color:var(--rule);
}
.fishtail{
  margin-top:calc(var(--cell) * 5);
  width:calc(var(--gutter) * .62);height:calc(var(--gutter) * .5);
  background:currentColor;clip-path:polygon(0 0,100% 0,50% 100%);
}
.folio{
  margin-top:auto;margin-bottom:calc(var(--cell) * 1.2);
  font-size:calc(var(--gutter) * .62);line-height:1;
}

/* ── pager & stats ───────────────────────────────────────────────────────── */
.pager{
  display:flex;align-items:center;justify-content:center;gap:.9rem;
  padding:.4rem 0 .55rem;
}
.pg{
  font:inherit;font-size:.85rem;line-height:1;cursor:pointer;
  width:2.1rem;height:2.1rem;border-radius:999px;
  border:1px solid var(--line);background:var(--chrome);color:var(--ink);
  -webkit-tap-highlight-color:transparent;
}
.pg:disabled{opacity:.35;cursor:default}
.folio-label{font-variant-numeric:tabular-nums;font-size:.85rem;color:var(--dim);min-width:5rem;text-align:center}

.stats{
  display:flex;gap:1rem;align-items:baseline;
  padding:.45rem .9rem max(env(safe-area-inset-bottom),.45rem);
  border-top:1px solid var(--line);background:var(--chrome);
  font-size:.78rem;color:var(--dim);
}
/* The count is the disclosure — the red squares are only ever the sheet you are
   looking at, and in `text` view there is no sheet at all. Only the verdict
   takes the alert color; the character and column counts beside it are not the
   thing being reported on. A clean result stays dim, because the good news is
   the absence of red and does not need its own color to say so. */
.verdict.flagged{color:var(--alert-ui)}
.hint{margin-left:auto;text-align:right;color:var(--accent)}

