/* ==========================================================================
   Ligbron — one stylesheet, no build step.
   Light and dark, screen and paper.
   ========================================================================== */

:root {
    --bg:        #faf7f2;
    --bg-alt:    #f2ede4;
    --surface:   #ffffff;
    --surface-2: #f7f4ee;
    --ink:       #221f1b;
    --ink-soft:  #5c5750;
    --ink-faint: #8b857c;
    --line:      #e3ddd2;
    --line-soft: #efeae1;

    --accent:      #9a6a1f;   /* candle */
    --accent-soft: #f6ecd9;
    --accent-ink:  #7c5416;

    --deep:      #2c3648;     /* headers, primary buttons */
    --deep-soft: #e8ebf0;

    --ok:      #2f6b46;
    --ok-soft: #e4f0e8;
    --warn:      #9a5b12;
    --warn-soft: #fbeedb;
    --danger:      #a32f2a;
    --danger-soft: #fbe7e5;

    --radius: 12px;
    --radius-sm: 8px;
    --shadow: 0 1px 2px rgba(34,31,27,.05), 0 4px 14px rgba(34,31,27,.05);
    --shadow-lg: 0 2px 6px rgba(34,31,27,.07), 0 14px 40px rgba(34,31,27,.09);

    --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --serif: Georgia, "Iowan Old Style", "Palatino Linotype", "Times New Roman", serif;
}

@media (prefers-color-scheme: dark) {
    :root {
        --bg:        #14161a;
        --bg-alt:    #1a1d22;
        --surface:   #1c1f25;
        --surface-2: #22262d;
        --ink:       #e9e5dd;
        --ink-soft:  #b2ada3;
        --ink-faint: #837e75;
        --line:      #2e333b;
        --line-soft: #262a31;

        --accent:      #dda94f;
        --accent-soft: #33291a;
        --accent-ink:  #edc379;

        --deep:      #93a6c8;
        --deep-soft: #232a36;

        --ok:      #6ec08f;
        --ok-soft: #1b2a21;
        --warn:      #d99a45;
        --warn-soft: #2d2317;
        --danger:      #e08078;
        --danger-soft: #2e1e1d;

        --shadow: 0 1px 2px rgba(0,0,0,.3), 0 4px 14px rgba(0,0,0,.25);
        --shadow-lg: 0 2px 6px rgba(0,0,0,.35), 0 14px 40px rgba(0,0,0,.4);
    }
}

/* Explicit user choice wins over the device setting, in both directions. */
[data-theme="light"] {
    --bg:#faf7f2; --bg-alt:#f2ede4; --surface:#fff; --surface-2:#f7f4ee;
    --ink:#221f1b; --ink-soft:#5c5750; --ink-faint:#8b857c;
    --line:#e3ddd2; --line-soft:#efeae1;
    --accent:#9a6a1f; --accent-soft:#f6ecd9; --accent-ink:#7c5416;
    --deep:#2c3648; --deep-soft:#e8ebf0;
    --ok:#2f6b46; --ok-soft:#e4f0e8; --warn:#9a5b12; --warn-soft:#fbeedb;
    --danger:#a32f2a; --danger-soft:#fbe7e5;
}
[data-theme="dark"] {
    --bg:#14161a; --bg-alt:#1a1d22; --surface:#1c1f25; --surface-2:#22262d;
    --ink:#e9e5dd; --ink-soft:#b2ada3; --ink-faint:#837e75;
    --line:#2e333b; --line-soft:#262a31;
    --accent:#dda94f; --accent-soft:#33291a; --accent-ink:#edc379;
    --deep:#93a6c8; --deep-soft:#232a36;
    --ok:#6ec08f; --ok-soft:#1b2a21; --warn:#d99a45; --warn-soft:#2d2317;
    --danger:#e08078; --danger-soft:#2e1e1d;
}

*, *::before, *::after { box-sizing: border-box; }

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

body {
    margin: 0;
    background: var(--bg);
    color: var(--ink);
    font: 16px/1.6 var(--sans);
    -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 { margin: 0 0 .5em; line-height: 1.25; font-weight: 650; letter-spacing: -.01em; }
h1 { font-size: 1.6rem; }
h2 { font-size: 1.22rem; }
h3 { font-size: 1.02rem; }
p { margin: 0 0 1em; }
a { color: var(--accent-ink); text-decoration-color: color-mix(in srgb, var(--accent) 40%, transparent); text-underline-offset: 2px; }
a:hover { text-decoration-color: currentColor; }
hr { border: 0; border-top: 1px solid var(--line); margin: 1.25rem 0; }
small { font-size: .82rem; }
mark { background: var(--accent-soft); color: inherit; padding: 0 .12em; border-radius: 3px; }

.skip { position: absolute; left: -9999px; }
.skip:focus { left: 1rem; top: 1rem; z-index: 99; background: var(--surface); padding: .6rem 1rem; border-radius: var(--radius-sm); }

/* ==========================================================================
   Chrome
   ========================================================================== */

.topbar {
    position: sticky; top: 0; z-index: 40;
    display: flex; align-items: center; gap: 1rem;
    padding: .6rem 1.1rem;
    background: color-mix(in srgb, var(--surface) 92%, transparent);
    backdrop-filter: saturate(160%) blur(10px);
    border-bottom: 1px solid var(--line);
}

.brand { display: flex; align-items: center; gap: .6rem; text-decoration: none; color: inherit; flex: 0 0 auto; }
.brand-mark { width: 34px; height: 34px; display: block; border-radius: 6px; }
.brand-text { display: flex; flex-direction: column; line-height: 1.15; }
.brand-text strong { font-size: 1.02rem; letter-spacing: .01em; }
.brand-text small { color: var(--ink-faint); font-size: .72rem; }

.topsearch { flex: 1 1 auto; max-width: 34rem; }
.topsearch input {
    width: 100%; padding: .5rem .85rem;
    border: 1px solid var(--line); border-radius: 999px;
    background: var(--bg-alt); color: inherit; font: inherit; font-size: .92rem;
}
.topsearch input:focus { outline: 2px solid var(--accent); outline-offset: 1px; background: var(--surface); }

.topbar-actions { display: flex; align-items: center; gap: .45rem; flex: 0 0 auto; }

.icon-link {
    display: grid; place-items: center; width: 2rem; height: 2rem;
    border-radius: 50%; text-decoration: none; color: var(--ink-soft); font-size: 1rem;
}
.icon-link:hover { background: var(--bg-alt); color: var(--ink); }

.vault-pill {
    display: inline-flex; align-items: center; gap: .4rem;
    padding: .3rem .7rem; border-radius: 999px;
    font-size: .78rem; font-weight: 600; text-decoration: none;
    border: 1px solid transparent;
}
.vault-pill.is-open   { background: var(--ok-soft); color: var(--ok); border-color: color-mix(in srgb, var(--ok) 25%, transparent); }
.vault-pill.is-locked { background: var(--warn-soft); color: var(--warn); border-color: color-mix(in srgb, var(--warn) 25%, transparent); }

.langswitch { display: inline-flex; border: 1px solid var(--line); border-radius: 999px; overflow: hidden; }
.langswitch button {
    border: 0; background: transparent; color: var(--ink-faint);
    font: inherit; font-size: .72rem; font-weight: 700; letter-spacing: .04em;
    padding: .28rem .55rem; cursor: pointer;
}
.langswitch button.is-on { background: var(--deep-soft); color: var(--ink); }

.shell { display: grid; grid-template-columns: 13.5rem minmax(0, 1fr); gap: 0; align-items: start; }

.sidenav {
    position: sticky; top: 3.4rem;
    padding: 1rem .6rem; display: flex; flex-direction: column; gap: .1rem;
    border-right: 1px solid var(--line); min-height: calc(100vh - 3.4rem);
}
.sidenav a {
    display: flex; align-items: center; gap: .65rem;
    padding: .5rem .7rem; border-radius: var(--radius-sm);
    text-decoration: none; color: var(--ink-soft); font-size: .9rem; font-weight: 500;
}
.sidenav a:hover { background: var(--bg-alt); color: var(--ink); }
.sidenav a.is-active { background: var(--accent-soft); color: var(--accent-ink); font-weight: 650; }
.sidenav .ni { width: 1.1rem; text-align: center; opacity: .85; }
.sidenav hr { margin: .6rem .4rem; }

.main { padding: 1.4rem 1.6rem 5rem; max-width: 74rem; }

/* --------------------------------------------------------------------------
   Narrow screens. A tablet in portrait is the main way this app is used, so
   this is not an afterthought for phones — it is the primary layout.

   The side column becomes a bar across the top. The names stay: a row of
   ✦ ◈ ◇ ❖ ◉ without words is a memory test, and nobody should have to learn
   which lozenge means Weddings. On a tablet there is room to wrap them onto
   two lines and show everything at once; on a phone the row scrolls sideways,
   with the most-used pages first.
   -------------------------------------------------------------------------- */
@media (max-width: 860px) {
    /* minmax(0, 1fr) rather than 1fr, and it matters. A grid item defaults to
       min-width:auto, which means it refuses to be narrower than its content —
       so the navigation row, which is deliberately wider than the screen and
       scrolls, would drag the whole page sideways with it. */
    .shell { grid-template-columns: minmax(0, 1fr); }
    .sidenav, .main { min-width: 0; }
    .sidenav {
        position: static; flex-direction: row; flex-wrap: wrap; min-height: 0;
        border-right: 0; border-bottom: 1px solid var(--line);
        padding: .5rem .6rem; gap: .2rem;
    }
    .sidenav hr { display: none; }
    .sidenav a { padding: .5rem .7rem; font-size: .88rem; white-space: nowrap; }
    .sidenav .ni { font-size: 1rem; }
    .main { padding: 1rem 1rem 4rem; }
    .brand-text, .vault-pill-text { display: none; }
}

@media (max-width: 620px) {
    /* Too narrow to wrap without eating half the screen: one scrolling row.
       The names still show — swiping past a word you can read beats guessing
       at a symbol you cannot. */
    .sidenav { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }
    .sidenav::-webkit-scrollbar { display: none; }
    .main { padding: .9rem .8rem 4rem; }

    /* The header runs out of room first. Sharing one line between a logo, a
       search box, the vault pill, two language buttons and two icons leaves
       the search box about a centimetre wide — present, and useless. Give it
       the second line to itself. */
    .topbar { flex-wrap: wrap; gap: .5rem .7rem; padding: .55rem .8rem; }
    .topsearch { order: 3; flex: 1 0 100%; max-width: none; }
    .topbar-actions { margin-left: auto; }
}

/* ==========================================================================
   Building blocks
   ========================================================================== */

.page-head {
    display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between;
    gap: 1rem; margin-bottom: 1.2rem;
}
.page-head h1 { margin-bottom: .15rem; }
.page-head .lede { color: var(--ink-soft); margin: 0; max-width: 46rem; font-size: .95rem; }
.page-actions { display: flex; gap: .5rem; flex-wrap: wrap; align-items: center; }

/* The accreditation badge in the corner of the dashboard. Sized to the height
   of the heading beside it so the row does not grow to accommodate it. */
/* Her ACCSA badge on the dashboard. Its own corner rather than a place in
   the button row, and big enough to read as a badge — at 3.6rem it looked
   like a stray icon stuck to the search button. */
.hero-badge {
    height: 6rem; width: auto; display: block; flex: 0 0 auto;
    margin-left: 1rem; align-self: flex-start;
}
@media (max-width: 900px) { .hero-badge { height: 4.6rem; margin-left: .6rem; } }
@media (max-width: 620px) { .hero-badge { height: 3.4rem; margin-left: 0; } }

.card {
    background: var(--surface); border: 1px solid var(--line);
    border-radius: var(--radius); padding: 1.1rem 1.2rem;
    box-shadow: var(--shadow); margin-bottom: 1.1rem;
}
.card-tight { padding: .8rem .95rem; }
.card > h2:first-child, .card > h3:first-child { margin-top: 0; }
.card-head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; margin-bottom: .8rem; }
.card-head h2, .card-head h3 { margin: 0; }

.grid { display: grid; gap: 1.1rem; }
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr)); }
.split { display: grid; grid-template-columns: minmax(0, 1.7fr) minmax(0, 1fr); gap: 1.1rem; align-items: start; }
/* minmax(0, 1fr), not 1fr — see the note on .shell. A date or time field has a
   wide minimum of its own, and a plain 1fr column will widen to fit it rather
   than let it shrink, taking the page sideways with it. */
@media (max-width: 900px) { .split { grid-template-columns: minmax(0, 1fr); } }

.muted { color: var(--ink-soft); }
.faint { color: var(--ink-faint); }
.tiny { font-size: .78rem; }
.center { text-align: center; }
.right { text-align: right; }
.mt { margin-top: 1rem; }
.mb0 { margin-bottom: 0; }
.stack > * + * { margin-top: .8rem; }

/* Buttons ---------------------------------------------------------------- */

.btn, button.btn, a.btn {
    display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
    padding: .48rem .95rem; border-radius: var(--radius-sm);
    border: 1px solid var(--line); background: var(--surface); color: var(--ink);
    font: inherit; font-size: .88rem; font-weight: 600; text-decoration: none;
    cursor: pointer; transition: background .12s, border-color .12s, transform .05s;
}
.btn:hover { background: var(--bg-alt); }
.btn:active { transform: translateY(1px); }
/* Primary and accent buttons are deliberately black-on-white in BOTH themes.
   They previously derived their text colour from the current theme, which is
   how "+ Nuwe huwelik" ended up dark-on-dark. Fixed values cannot drift, and
   black on white is the most legible combination there is — which matters on
   a laptop screen in a church hall. */
.btn-primary,
.btn-accent {
    background: #ffffff;
    color: #14120f;
    font-weight: 700;
}
.btn-primary { border: 1.5px solid #14120f; }
.btn-accent  { border: 1.5px solid var(--accent); }

.btn-primary:hover,
.btn-accent:hover { background: #f1ece2; color: #14120f; }

.btn-primary:active,
.btn-accent:active { background: #e6dfd2; }
.btn-ghost { background: transparent; border-color: transparent; color: var(--ink-soft); }
.btn-ghost:hover { background: var(--bg-alt); color: var(--ink); }
.btn-danger { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 35%, transparent); }
.btn-danger:hover { background: var(--danger-soft); }
.btn-sm { padding: .3rem .6rem; font-size: .78rem; }
.btn-block { width: 100%; }

/* WhatsApp. The one green in the whole application, and it is WhatsApp's own
   green rather than a colour from our palette — deliberately. This button
   leaves the app and hands over to another one, and a hand-over should not be
   dressed up to look like the rest of the page. It is also the only colour
   she will find without reading, which on a tablet held one-handed is the
   whole point.

   #128c7e is the darker of WhatsApp's two greens: the brighter #25d366 does
   not carry white text at accessible contrast, and this button always has
   text on it. */
.btn-wa {
    background: #128c7e;
    border-color: #0f7a6d;
    color: #ffffff;
    font-weight: 700;
}
.btn-wa:hover  { background: #0f7a6d; color: #ffffff; }
.btn-wa:active { background: #0d6b60; }

/* No number on file. Still tappable — it opens WhatsApp on its contact list —
   but it should not promise a chat that will not be there. */
.btn-wa.is-empty {
    background: transparent;
    color: #128c7e;
    border-color: color-mix(in srgb, #128c7e 40%, transparent);
    font-weight: 600;
}
.btn-wa.is-empty:hover { background: color-mix(in srgb, #128c7e 10%, transparent); color: #128c7e; }

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .btn-wa         { background: #1da192; border-color: #25b8a6; }
    :root:not([data-theme="light"]) .btn-wa:hover   { background: #25b8a6; }
    :root:not([data-theme="light"]) .btn-wa.is-empty { background: transparent; color: #4fd1c0; }
}
:root[data-theme="dark"] .btn-wa          { background: #1da192; border-color: #25b8a6; }
:root[data-theme="dark"] .btn-wa:hover    { background: #25b8a6; }
:root[data-theme="dark"] .btn-wa.is-empty { background: transparent; color: #4fd1c0; }

/* Forms ------------------------------------------------------------------ */

.field { margin-bottom: .9rem; }
.field > label, .label {
    display: block; margin-bottom: .3rem;
    font-size: .8rem; font-weight: 650; color: var(--ink-soft); letter-spacing: .01em;
}
.field .hint { display: block; margin-top: .3rem; font-size: .78rem; color: var(--ink-faint); }

/* A hint that has turned into a warning — a mistyped identity number. It stays
   a hint rather than becoming an error box, because she is mid-sentence with a
   client and nothing here should stop her saving what she has. */
.field .hint.is-wrong { color: var(--danger); font-weight: 600; }

input[type=text], input[type=email], input[type=tel], input[type=password], input[type=date],
input[type=datetime-local], input[type=number], input[type=search], input[type=time],
select, textarea {
    width: 100%; padding: .5rem .65rem;
    border: 1px solid var(--line); border-radius: var(--radius-sm);
    background: var(--surface); color: var(--ink); font: inherit; font-size: .92rem;
}

/* A box that offers a list has to look like one.
   A datalist is invisible until you happen to type the first letter of
   something in it, so without this the whole point is lost: she carries on
   typing every answer out by hand, never knowing the list was there. The
   caret is the one a dropdown already wears, so it needs no explaining.

   It has to come after the rule above, which sets `background` as a shorthand
   and would otherwise wipe this image out. */
input[list] {
    background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%238b857c' stroke-width='1.4' stroke-linecap='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right .6rem center;
    background-size: .62rem;
    padding-right: 1.9rem;
}
/* Date and time fields carry an intrinsic minimum width — the browser sizes
   them to "yyyy/mm/dd, --:-- --" and will push a whole layout sideways rather
   than shrink one. width:100% does not override that on its own. */
input[type=date], input[type=datetime-local], input[type=time], input[type=number] {
    min-width: 0;
}

textarea { min-height: 6.5rem; resize: vertical; line-height: 1.6; }
textarea.tall { min-height: 14rem; }
textarea.mono { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: .86rem; }
input:focus, select:focus, textarea:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
select { appearance: none; background-image: linear-gradient(45deg, transparent 50%, var(--ink-faint) 50%), linear-gradient(135deg, var(--ink-faint) 50%, transparent 50%); background-position: calc(100% - 15px) 55%, calc(100% - 10px) 55%; background-size: 5px 5px, 5px 5px; background-repeat: no-repeat; padding-right: 2rem; }

.row { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr)); gap: 0 .9rem; }

.check { display: flex; align-items: flex-start; gap: .55rem; font-size: .9rem; margin-bottom: .6rem; }
.check input { margin-top: .25rem; }

.inline-form { display: flex; gap: .5rem; flex-wrap: wrap; align-items: flex-end; }
.inline-form .field { margin-bottom: 0; flex: 1 1 10rem; }

/* Flash ------------------------------------------------------------------ */

/* Back and home, at the top of every page but the dashboard.

   Above the flash messages and the heading, because it is furniture rather
   than content: it should sit in the same place on every screen so she can
   reach for it without looking. Quiet on purpose — it is used constantly
   and should never compete with the actual page.

   Sticky so it survives a long client file. On a tablet the browser's own
   back button is off-screen and, once the app is added to the home screen,
   gone altogether; scrolling to the top of a session history to get out of
   it is exactly the annoyance this removes. */
.wayback {
    position: sticky; top: 3.4rem; z-index: 5;
    display: flex; gap: .4rem; align-items: center;
    margin: -.35rem 0 .9rem; padding: .35rem 0;
    background: var(--bg);
}
.wayback .btn { padding: .3rem .7rem; }

/* 3.4rem is the height of the sticky header above it — the same offset the
   sidebar uses, so the two line up and neither slides under the other. */

@media (max-width: 620px) {
    /* Below this the header wraps to two lines to give the search box room,
       so its height is no longer 3.4rem and a fixed offset would leave this
       bar floating over the page or hidden behind it. Nothing is lost by
       letting it scroll away on a screen this small. */
    .wayback { position: static; }
}

@media print { .wayback { display: none; } }

.flash {
    padding: .65rem .9rem; border-radius: var(--radius-sm);
    margin-bottom: 1rem; font-size: .9rem; border: 1px solid transparent;
}
.flash-ok    { background: var(--ok-soft);    color: var(--ok);    border-color: color-mix(in srgb, var(--ok) 25%, transparent); }
.flash-error { background: var(--danger-soft);color: var(--danger);border-color: color-mix(in srgb, var(--danger) 25%, transparent); }
.flash-info  { background: var(--deep-soft);  color: var(--ink);   border-color: var(--line); }

/* A button that reads as a link — "discard", sitting inside a message rather
   than standing on its own as an action. */
.linkish {
    background: none; border: 0; padding: 0; margin-left: .5rem;
    font: inherit; font-size: .82rem; color: inherit;
    text-decoration: underline; cursor: pointer;
}

/* Tags & badges ---------------------------------------------------------- */

.tag {
    display: inline-flex; align-items: center; gap: .3rem;
    padding: .12rem .5rem; border-radius: 999px;
    font-size: .72rem; font-weight: 650; letter-spacing: .01em;
    background: var(--bg-alt); color: var(--ink-soft); border: 1px solid var(--line-soft);
}
.tag-ok     { background: var(--ok-soft);     color: var(--ok);     border-color: transparent; }
.tag-warn   { background: var(--warn-soft);   color: var(--warn);   border-color: transparent; }
.tag-danger { background: var(--danger-soft); color: var(--danger); border-color: transparent; }
.tag-accent { background: var(--accent-soft); color: var(--accent-ink); border-color: transparent; }

/* Lists ------------------------------------------------------------------ */

.list { list-style: none; margin: 0; padding: 0; }
.list > li { border-bottom: 1px solid var(--line-soft); }
.list > li:last-child { border-bottom: 0; }

.item {
    display: flex; align-items: center; gap: .9rem;
    padding: .7rem .2rem; text-decoration: none; color: inherit;
}
.item:hover { background: var(--bg-alt); border-radius: var(--radius-sm); }
.item-main { flex: 1 1 auto; min-width: 0; }
.item-title { font-weight: 600; font-size: .95rem; }
.item-sub { color: var(--ink-faint); font-size: .8rem; }
.item-side { flex: 0 0 auto; text-align: right; font-size: .8rem; color: var(--ink-soft); }

.when { font-variant-numeric: tabular-nums; font-weight: 600; font-size: .82rem; }
.when-late { color: var(--danger); }

/* A list row that carries its own actions.
   The row stays a plain link — clicking it still opens the thing — and the
   ⋯ button beside it drops a small panel instead of sending her to another
   page to change one date. */
.row-with-tools { display: flex; align-items: center; gap: .25rem; }
.row-with-tools > .item { flex: 1 1 auto; min-width: 0; }

/* The little picture beside a document.

   A fixed square whatever the picture's shape, with the image covering it
   — a list where every row is a different height is much harder to run an
   eye down than one where they all match, and a page scanned slightly
   crooked should not make its row taller than the rest. */
.file-thumb {
    flex: 0 0 auto;
    width: 52px; height: 52px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--line);
    object-fit: cover;
    background: var(--bg-alt);
}

/* The same square, for a document with no picture of its own. */
.file-thumb-icon {
    display: grid; place-items: center;
    font-size: 1.4rem; color: var(--ink-soft);
}

/* An index of notes: one line each, tight enough that a hundred of them
   can be run down with the eye rather than scrolled through.

   A client with eleven years of history has a lot of notes, and her file
   shows all of them — showing part of somebody's record is worse than a
   long page. This is what makes "all of them" readable: the ordinary row
   padding turned down, and each row kept to a single line. */
.note-index .item { padding: .4rem .2rem; gap: .6rem; }
.note-index .item-title { font-size: .9rem; font-weight: 550; }
.note-index .item-sub { font-size: .76rem; }
.note-index .item-side { font-variant-numeric: tabular-nums; font-weight: 650; }

/* The year, marking where one ends in the logbook.

   Reading twelve years of history straight through, "4 March" means very
   little on its own — but repeating 2019 on nineteen consecutive entries
   is noise. So it is written once, where it changes, and sits in the
   margin rather than in the flow of the entries. */
.log-year {
    font-size: .95rem; font-weight: 700; letter-spacing: .04em;
    color: var(--ink-faint);
    margin: 1.4rem 0 .6rem; padding-bottom: .25rem;
    border-bottom: 1px solid var(--line);
}
.log-year:first-child { margin-top: 0; }

/* A cancelled appointment.

   Solid red rather than the faded grey it used to be. Faded reads as
   "unimportant" and she skimmed straight past it; a cancelled hour is the
   opposite of unimportant, because the mistake it guards against is
   driving to Parys for somebody who is not coming.

   Everything inside is forced white in one rule. The row is full of things
   that set their own colour — the faint sub-line, the tags, the person's
   name — and picking them off one by one leaves dark grey text on dark red
   the first time a new tag is added to the row.

   The red is written out rather than taken from --danger, which is a pale
   salmon in the dark theme: white text on it fails contrast badly. This
   one clears 6.8:1 against white and reads the same in both themes, which
   a solid block of colour should. */
.row-cancelled {
    background: #9b2c27;
    border-radius: var(--radius-sm);
    padding: 0 .5rem;
}
.row-cancelled, .row-cancelled * { color: #fff; }
.row-cancelled .item:hover { background: transparent; }
.row-cancelled .tag {
    background: rgba(255, 255, 255, .18);
    border-color: rgba(255, 255, 255, .35);
}

/* Buttons sitting on a list row rather than behind a menu. They wrap onto
   their own line on a narrow screen instead of squeezing the title out. */
.row-actions { display: flex; flex-wrap: wrap; gap: .3rem; flex: 0 0 auto; }
.row-actions > .btn { white-space: nowrap; }
@media (max-width: 640px) {
    .row-with-tools { flex-wrap: wrap; }
    .row-actions { width: 100%; padding: 0 0 .5rem; }
}

.tools { position: relative; flex: 0 0 auto; }
.tools > summary {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 2rem; cursor: pointer; list-style: none;
}
.tools > summary::-webkit-details-marker { display: none; }
.tools[open] > summary { background: var(--bg-alt); color: var(--ink); }

.tools-panel {
    position: absolute; z-index: 30; right: 0; top: calc(100% + .3rem);
    width: min(19rem, 78vw);
    padding: .85rem;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    box-shadow: 0 12px 28px rgb(0 0 0 / .16);
    text-align: left;
}
.tools-panel .field { margin-bottom: .55rem; }
.tools-panel input, .tools-panel select { width: 100%; }

/* Deleting is separated by a line and tinted, so the destructive half of the
   panel can never be mistaken for the half that only moves a date. */
.tools-danger {
    margin-top: .85rem; padding-top: .75rem;
    border-top: 1px solid var(--line);
}
.tools-danger .field > label { color: var(--danger); }

.empty {
    padding: 2rem 1rem; text-align: center; color: var(--ink-faint);
    border: 1px dashed var(--line); border-radius: var(--radius); font-size: .9rem;
}

/* ==========================================================================
   Reports — bars and a trend.

   One hue per chart, on purpose. Every row of a chart here is the same
   measure, so a second colour would claim a distinction that is not in the
   data, and would ask a colour-blind reader to separate hues that mean
   nothing. Identity comes from the label beside each bar, never from colour.

   Labels and values wear the ordinary text colours. Only the bar carries the
   accent — a number printed in the series colour is the fastest way to make a
   figure unreadable against its own background.
   ========================================================================== */

/* Read aloud, never drawn. The heading above each chart says the same thing
   to everyone else, so repeating it on screen would be clutter. */
.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;
}

.bars { width: 100%; border-collapse: collapse; }
.bars th, .bars td { padding: .28rem 0; vertical-align: middle; font-weight: 400; }
/* A share rather than a fixed width: these charts sit in half-width cards on
   a laptop and full-width ones on a phone, and 11rem of label leaves almost
   no track left in the narrow case. */
.bars th[scope=row] {
    width: 42%; max-width: 13rem; padding-right: .7rem; text-align: left;
    font-size: .84rem; color: var(--ink-soft); font-weight: 400;
    overflow-wrap: anywhere;
}
.bars-cell { width: auto; }
.bars-track {
    /* The track is the axis. It stays recessive; the fill is the only mark.
       A block span rather than the table cell, so its height is its own and
       the rounded ends are drawn once instead of against the row's height. */
    display: block; height: 10px; width: 100%;
    background: var(--line-soft);
    border-radius: 999px;
    overflow: hidden;
}
.bars-fill {
    display: block; height: 100%;
    background: var(--accent);
    /* Square where it meets the baseline, rounded at the reading end. */
    border-radius: 0 4px 4px 0;
    min-width: 3px;
}
.bars-value {
    width: 4.5rem; padding-left: .7rem; text-align: right;
    font-size: .84rem; font-weight: 600; font-variant-numeric: tabular-nums;
    color: var(--ink);
}
.bars.is-danger .bars-fill { background: var(--danger); }
.bars.is-ok     .bars-fill { background: var(--ok); }

.sub-h {
    margin: 1.1rem 0 .4rem; font-size: .78rem; font-weight: 700;
    letter-spacing: .04em; text-transform: uppercase; color: var(--ink-faint);
}
.card > .sub-h:first-of-type { margin-top: .2rem; }

/* --- The month trend --------------------------------------------------- */
.trend {
    display: flex; align-items: flex-end; gap: 2px;
    height: 8.5rem; padding-top: 1.1rem;
    border-bottom: 1px solid var(--line);
}
.trend-col {
    flex: 1 1 0; min-width: 0;
    display: flex; flex-direction: column; align-items: center; justify-content: flex-end;
    height: 100%; position: relative;
}
.trend-bar {
    display: block; width: 100%; max-width: 2.4rem;
    background: var(--accent);
    border-radius: 4px 4px 0 0;
    min-height: 2px;
}
.trend-n {
    position: absolute; top: -1rem;
    font-size: .68rem; font-variant-numeric: tabular-nums; color: var(--ink-faint);
}
.trend-l {
    position: absolute; bottom: -1.2rem;
    font-size: .68rem; color: var(--ink-faint); white-space: nowrap;
}
.trend + .trend-table { margin-top: 1.6rem; }
.trend-table > summary { cursor: pointer; }

/* --- The period filter -------------------------------------------------- */
.periods { display: flex; flex-wrap: wrap; gap: .8rem; align-items: center; justify-content: space-between; }
.period-pills { display: flex; flex-wrap: wrap; gap: .35rem; }
.period-range { display: flex; flex-wrap: wrap; gap: .4rem; align-items: center; }
/* A date input has a wide minimum of its own and will happily push the page
   sideways rather than shrink. Give it a basis it may fall below. */
.period-range input[type=date] {
    padding: .3rem .5rem; font-size: .82rem;
    flex: 1 1 8rem; min-width: 0; width: auto;
}
@media (max-width: 620px) {
    .period-range { width: 100%; }
    .period-range label { width: 100%; }
}

/* A tile that is a figure rather than a way in — no hover, no arrow. */
.tile.is-flat { cursor: default; }
.tile.is-flat:hover { border-color: var(--line); transform: none; }

.kv { display: grid; grid-template-columns: 1fr auto; gap: .35rem .8rem; margin: 0 0 .6rem; }
.kv dt { font-size: .86rem; color: var(--ink-soft); }
.kv dd { margin: 0; font-weight: 600; font-variant-numeric: tabular-nums; text-align: right; }
.kv dd.is-ok { color: var(--ok); }
.kv dd.is-danger { color: var(--danger); }

.stat { display: flex; flex-direction: column; gap: .1rem; }
.stat-n { font-size: 1.9rem; font-weight: 700; line-height: 1; letter-spacing: -.02em; }
.stat-l { font-size: .8rem; color: var(--ink-faint); }

.tabs { display: flex; gap: .3rem; flex-wrap: wrap; margin-bottom: 1rem; }
.tabs a {
    padding: .35rem .8rem; border-radius: 999px; font-size: .84rem; font-weight: 600;
    text-decoration: none; color: var(--ink-soft); border: 1px solid var(--line);
}
.tabs a.is-on { background: var(--deep-soft); color: var(--ink); border-color: transparent; }

/* ==========================================================================
   Scripture
   ========================================================================== */

.verse-block {
    font-family: var(--serif); font-size: 1.02rem; line-height: 1.75;
    color: var(--ink);
}
.verse-block p { margin: 0 0 .55rem; }
.verse-n {
    font-family: var(--sans); font-size: .68rem; font-weight: 700;
    color: var(--accent); vertical-align: .35em; margin-right: .28em;
}
.verse-block .is-highlight { background: var(--accent-soft); border-radius: 4px; }

/* --- Voice dictation ---------------------------------------------------- */

.dictate {
    display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
    margin-top: .4rem;
}

.dictate-mic {
    display: inline-flex; align-items: center; gap: .35rem;
    padding: .28rem .7rem; border-radius: 999px;
    border: 1px solid var(--line); background: var(--surface); color: var(--ink);
    font: inherit; font-size: .78rem; font-weight: 600; cursor: pointer;
}
.dictate-mic:hover { background: var(--bg-alt); }

.dictate.is-listening .dictate-mic {
    background: var(--danger-soft); color: var(--danger);
    border-color: color-mix(in srgb, var(--danger) 45%, transparent);
    animation: dictate-pulse 1.4s ease-in-out infinite;
}
@keyframes dictate-pulse {
    0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--danger) 35%, transparent); }
    50%      { box-shadow: 0 0 0 .35rem transparent; }
}

.dictate-lang { display: inline-flex; border: 1px solid var(--line); border-radius: 999px; overflow: hidden; }
.dictate-lang button {
    border: 0; background: transparent; color: var(--ink-faint);
    font: inherit; font-size: .68rem; font-weight: 700; letter-spacing: .04em;
    padding: .26rem .5rem; cursor: pointer;
}
.dictate-lang button.is-on { background: var(--accent-soft); color: var(--accent-ink); }

.dictate-status { min-width: 1rem; }
.dictate-warn { color: var(--warn); flex: 1 1 12rem; }

/* --- Original languages ------------------------------------------------
   Hebrew with full pointing is unreadable at body size, and the cantillation
   marks need the line height. These stacks list fonts that ship with Windows,
   macOS and Linux — the CSP blocks webfonts, and it should. */

.verse-block[dir="rtl"] {
    direction: rtl;
    text-align: right;
    font-family: "SBL Hebrew", "Ezra SIL", "Taamey Frank CLM", "Times New Roman",
                 "David", "Frank Ruehl CLM", "Noto Serif Hebrew", "Arial Hebrew", serif;
    font-size: 1.45rem;
    line-height: 2.1;
    letter-spacing: 0;
}
.verse-block[dir="rtl"] .verse-n {
    margin-right: 0;
    margin-left: .35em;
    vertical-align: .25em;
}

/* Greek needs no direction change, only a face that has the accents. */
.verse-block[lang="grc"] {
    font-family: "SBL Greek", "Gentium Plus", "Galatia SIL", "Cardo",
                 "Palatino Linotype", "Noto Serif", Georgia, serif;
    font-size: 1.12rem;
    line-height: 1.95;
}

.passage[dir="rtl"] {
    border-left: 0;
    border-right: 3px solid var(--accent);
    padding: .1rem .9rem .1rem 0;
}
.passage[dir="rtl"] .passage-head { flex-direction: row-reverse; }

/* The reference itself stays left-to-right — "Genesis 1:1" is not Hebrew. */
.passage-ref { direction: ltr; unicode-bidi: isolate; }

/* The Hebrew acrostic letter at the head of a stanza — kept, because it is
   part of the translation, but set as a marker rather than as the first word
   of the sentence. */
.acrostic {
    display: inline-block;
    font-family: var(--sans);
    font-size: .62rem; font-weight: 700; letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--accent-ink);
    background: var(--accent-soft);
    padding: .1em .45em; border-radius: 3px;
    margin-right: .45em;
    vertical-align: .18em;
}
[dir="rtl"] .acrostic { margin-right: 0; margin-left: .45em; }

@media print {
    .acrostic { background: none; color: #444; border: 1px solid #bbb; }
}

.original-tag {
    font-size: .68rem; font-weight: 700; letter-spacing: .06em;
    text-transform: uppercase; color: var(--accent-ink);
}

.passage {
    border-left: 3px solid var(--accent); padding: .1rem 0 .1rem .9rem;
    margin-bottom: 1.1rem;
}
.passage-head {
    display: flex; align-items: baseline; justify-content: space-between; gap: .8rem;
    margin-bottom: .3rem;
}
.passage-ref { font-weight: 700; font-size: .92rem; letter-spacing: .01em; }
.passage-tools { display: flex; gap: .35rem; align-items: center; opacity: .55; transition: opacity .12s; }
.passage:hover .passage-tools { opacity: 1; }

.pastoral {
    background: var(--accent-soft); border-radius: var(--radius);
    padding: .85rem 1rem; margin-bottom: 1rem;
    border-left: 3px solid var(--accent);
}
.pastoral h3 { font-size: .78rem; text-transform: uppercase; letter-spacing: .07em; color: var(--accent-ink); margin-bottom: .35rem; }
.pastoral p:last-child { margin-bottom: 0; }

.qlist { margin: 0; padding-left: 1.1rem; }
.qlist li { margin-bottom: .45rem; }

.topic-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 15rem), 1fr)); gap: .5rem; }
.topic-chip {
    display: block; padding: .55rem .75rem; border-radius: var(--radius-sm);
    border: 1px solid var(--line); background: var(--surface);
    text-decoration: none; color: inherit; font-size: .88rem; font-weight: 550;
}
.topic-chip:hover { border-color: var(--accent); background: var(--accent-soft); }

/* A run of subject chips that wraps rather than scrolls. */
.chips { display: flex; flex-wrap: wrap; gap: .35rem; margin: .3rem 0 1rem; }

/* Sending is a separate act from downloading, so it gets its own block with
   its own button underneath the address — not a button floating above the
   field it depends on. */
.sendblock {
    margin-top: 1rem;
    padding: .9rem 1rem 1rem;
    border: 1px solid var(--line);
    border-radius: 10px;
    background: var(--bg-alt);
}
.sendblock h4 { margin: 0 0 .5rem; font-size: .95rem; }

/* The document as it will read once filled in. Preserves her paragraphs
   without letting a long line push the page sideways. */
.doc-preview {
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    font-size: .92rem;
    line-height: 1.65;
    max-height: 26rem;
    overflow-y: auto;
    padding: .8rem 1rem;
    border-left: 3px solid var(--line);
    background: var(--bg-alt);
    border-radius: 0 8px 8px 0;
}

/* --- Signing on glass ---------------------------------------------------
   The pad has to be big enough to sign in with a finger. 150px is about the
   height of a real signature block on paper; below that people write small
   and it looks nothing like their hand. */
.signblock { border: 1px solid var(--line); border-radius: 12px; padding: .9rem 1rem 1rem; margin: 0 0 1rem; }
.signblock-head { display: flex; align-items: center; justify-content: space-between; gap: .6rem; flex-wrap: wrap; }
.signblock-head h4 { margin: 0; font-size: .95rem; }
.signblock-foot { display: flex; align-items: flex-end; justify-content: space-between; gap: .8rem; flex-wrap: wrap; margin-top: .6rem; }
.signblock-foot .field { flex: 1 1 14rem; margin: 0; }
.signblock-remove { margin-top: .5rem; text-align: right; }

.signpad {
    --sign-ink: var(--ink);
    position: relative;
    height: 150px;
    margin-top: .6rem;
    border: 1px dashed var(--line);
    border-radius: 10px;
    background: var(--bg);
    overflow: hidden;
}
.signpad canvas {
    position: absolute; inset: 0;
    width: 100%; height: 100%;
    /* Without this the browser pans the page instead of letting her sign. */
    touch-action: none;
    cursor: crosshair;
}
/* The line she signs on, so the box reads as a signature block. */
.signpad-rule {
    position: absolute; left: 8%; right: 8%; bottom: 34px;
    border-bottom: 1px solid var(--line);
    pointer-events: none;
}
.signpad-hint {
    position: absolute; left: 0; right: 0; bottom: 12px;
    text-align: center; font-size: .72rem; color: var(--ink-faint);
    pointer-events: none;
}
.signpad.is-signed .signpad-hint,
.signpad.is-signed .signpad-rule { opacity: 0; }

@media (max-width: 1200px), (pointer: coarse) {
    /* More room to sign where it is actually being signed. */
    .signpad { height: 190px; }
}
.topic-chip small { display: block; color: var(--ink-faint); font-weight: 400; font-size: .74rem; }

.cat-head { display: flex; align-items: center; gap: .5rem; margin: 1.4rem 0 .6rem; }
.cat-head h2 { margin: 0; font-size: 1rem; }
.cat-head .ci { font-size: 1.1rem; }

.compare-grid { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr)); }

.match { padding: .6rem 0; border-bottom: 1px solid var(--line-soft); }
.match:last-child { border-bottom: 0; }
.match-ref { font-size: .78rem; font-weight: 700; color: var(--accent-ink); text-decoration: none; }
/* Reference on the left, copy button on the right, on the same line. */
/* Dashboard tiles. Centred, equal, and every one of them a door: the number
   on its own would only be something to worry about. */
.tiles {
    display: grid; gap: .8rem; margin-bottom: 1.2rem;
    /* Three across on anything wider than a phone, stacked below that.
       auto-fit was leaving a lonely third tile on its own row. */
    grid-template-columns: repeat(3, 1fr);
}
@media (max-width: 34rem) { .tiles { grid-template-columns: 1fr; } }
.tile {
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: .25rem; text-align: center; text-decoration: none; color: inherit;
    background: var(--surface); border: 1px solid var(--line);
    border-radius: 14px; padding: 1.3rem .8rem 1rem;
    transition: border-color .12s, transform .12s;
}
.tile:hover { border-color: var(--accent); transform: translateY(-1px); }
.tile:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.tile-n { font-size: 2rem; font-weight: 700; line-height: 1.05; letter-spacing: -.02em; }
.tile.is-money .tile-n { font-size: 1.4rem; }
.tile.is-danger .tile-n { color: var(--danger); }
.tile-l { font-size: .82rem; color: var(--ink-faint); line-height: 1.35; }
.tile-go { font-size: .72rem; color: var(--accent-ink); opacity: 0; transition: opacity .12s; }
.tile:hover .tile-go, .tile:focus-visible .tile-go { opacity: 1; }
@media (hover: none) { .tile-go { opacity: .7; } }

/* Explain a verse: the surrounding context sits back so the passage itself
   stays the thing you read first. */
.ctx {
    font-family: var(--serif); font-size: .88rem; line-height: 1.6;
    color: var(--ink-faint); margin: .3rem 0;
}
.passage-body.focus {
    border-left: 3px solid var(--accent); padding-left: .9rem; margin: .6rem 0;
}
.passage-body.focus p { font-family: var(--serif); font-size: 1.02rem; line-height: 1.7; margin: .3rem 0; }

/* Questions people ask: collapsed by default so a hundred of them fit. */
.faq { border-bottom: 1px solid var(--line-soft); }
.faq:last-of-type { border-bottom: 0; }
.faq > summary {
    cursor: pointer; padding: .6rem .2rem; font-weight: 600;
    list-style: none; display: flex; gap: .5rem; align-items: baseline;
}
.faq > summary::-webkit-details-marker { display: none; }
.faq > summary::before { content: '+'; color: var(--ink-faint); font-weight: 400; }
.faq[open] > summary::before { content: '−'; }
.faq[open] > summary { color: var(--accent-ink); }
.faq-body { padding: 0 .2rem .8rem 1.2rem; }
.faq-body p { margin: .2rem 0 .5rem; }
.faq-refs a {
    display: inline-block; font-size: .78rem; font-weight: 700;
    margin: 0 .4rem .2rem 0; text-decoration: none; color: var(--accent-ink);
}
@media print { .faq > summary::before { content: ''; } .faq-body { display: block !important; } }

.match-head { display: flex; align-items: center; justify-content: space-between; gap: .5rem; }
.match-head .btn { opacity: .35; transition: opacity .12s; }
.match:hover .match-head .btn, .match-head .btn:focus-visible { opacity: 1; }
.match-body { font-family: var(--serif); font-size: .96rem; line-height: 1.65; margin-top: .15rem; }

/* Risk banner ------------------------------------------------------------ */

.alarm {
    border: 1px solid color-mix(in srgb, var(--danger) 40%, transparent);
    background: var(--danger-soft); color: var(--danger);
    border-radius: var(--radius); padding: .9rem 1.05rem; margin-bottom: 1.1rem;
}
.alarm h3 { color: inherit; margin-bottom: .3rem; font-size: .95rem; }
.alarm p:last-child, .alarm ul:last-child { margin-bottom: 0; }
.alarm a { color: inherit; font-weight: 700; }

.timeline { position: relative; padding-left: 1.3rem; }
.timeline::before { content: ""; position: absolute; left: .32rem; top: .5rem; bottom: .5rem; width: 2px; background: var(--line); }
.timeline-item { position: relative; padding-bottom: 1.1rem; }
.timeline-item::before {
    content: ""; position: absolute; left: -1.18rem; top: .45rem;
    width: .55rem; height: .55rem; border-radius: 50%;
    background: var(--accent); box-shadow: 0 0 0 3px var(--bg);
}

details.disc { border: 1px solid var(--line); border-radius: var(--radius-sm); padding: .5rem .8rem; margin-bottom: .6rem; background: var(--surface); }

/* "Will a message actually go?" — the answer, on the bridge page.

   Loud on purpose. It is the sentence somebody is looking for when they
   open this page at all, and it has to be findable without reading the
   form underneath it. */
.wa-diagnosis {
    margin-top: .9rem; padding: .7rem .9rem;
    border-radius: var(--radius-sm); border: 1px solid transparent;
    font-size: .88rem;
}
.wa-diagnosis.is-ok  { background: var(--ok-soft);     color: var(--ok);
                       border-color: color-mix(in srgb, var(--ok) 25%, transparent); }
.wa-diagnosis.is-not { background: var(--danger-soft); color: var(--danger);
                       border-color: color-mix(in srgb, var(--danger) 25%, transparent); }
.wa-diagnosis p { margin: .3rem 0 0; }

/* The paper-history box: yellow, with black on it.

   Not decoration. It is the only part of these forms that quietly writes
   into a different table than the form it sits in, it is folded shut by
   default, and it was looked for on four separate occasions and not found
   against the white of an ordinary fold-out. A pale tint was not enough;
   this is the colour of the sticky note it replaces.

   Written out rather than taken from the theme variables, and the same in
   light and dark. A block that exists to be spotted must not turn into a
   muted brown when the device switches to a dark theme in the evening,
   which is exactly when she does her writing up. Black on this yellow
   clears 15:1, comfortably past any contrast requirement. */
details.disc-history {
    background: #ffe873;
    border-color: #d9bc1f;
    border-left: 4px solid #a8880a;
    color: #000;
}

/* Every scrap of text inside, black and bold, including the parts that
   set their own colour and their own weight — the hints, the faint
   notes, the summary. One rule, because picking them off individually is
   how one of them stays small and grey on yellow the next time a line is
   added here.

   The hints in this box are the instructions for the one feature nobody
   finds by accident, printed at .78rem. Light grey at that size on a
   strong yellow is the worst of both: loud background, unreadable text. */
details.disc-history > summary,
details.disc-history label,
details.disc-history p,
details.disc-history span,
details.disc-history strong,
details.disc-history code {
    color: #000;
    font-weight: 600;
}
details.disc-history > summary { font-weight: 700; }

/* The fields themselves stay white paper, so what she types is read
   against the same background as everywhere else in the application —
   and at a normal weight, because a wall of bold pasted history is
   harder to read, not easier. */
details.disc-history input,
details.disc-history textarea,
details.disc-history select {
    background: #fff;
    color: #000;
    border-color: #a8880a;
    font-weight: 400;
}
details.disc-history input::placeholder,
details.disc-history textarea::placeholder {
    color: #5c5c5c;
    font-weight: 400;
}
details.disc > summary { cursor: pointer; font-weight: 600; font-size: .9rem; }
details.disc[open] > summary { margin-bottom: .6rem; }

.progress { height: .5rem; background: var(--bg-alt); border-radius: 999px; overflow: hidden; }
.progress > span { display: block; height: 100%; background: var(--accent); width: 0; transition: width .2s; }

table.data { width: 100%; border-collapse: collapse; font-size: .9rem; }
table.data th, table.data td { text-align: left; padding: .5rem .6rem; border-bottom: 1px solid var(--line-soft); }
table.data th { font-size: .76rem; text-transform: uppercase; letter-spacing: .05em; color: var(--ink-faint); font-weight: 700; }
/* Money and counts read far better against the right edge of their column. */
table.data th.right, table.data td.right { text-align: right; }
table.data tfoot td { border-bottom: 0; border-top: 2px solid var(--line); }

/* ==========================================================================
   Login / unlock gate
   ========================================================================== */

.gate { min-height: 100vh; display: grid; place-items: center; padding: 1.5rem; background: var(--bg); }

/* One card, two panels. The whole point is that it stops being a long
   column: who she is on the left, the way in on the right. */
.gate-card {
    width: min(46rem, 100%); background: var(--surface);
    border: 1px solid var(--line); border-radius: 16px;
    box-shadow: var(--shadow-lg); overflow: hidden;
    display: grid; grid-template-columns: 1fr;
}
@media (min-width: 46rem) {
    .gate-card { grid-template-columns: 17.5rem 1fr; }
}

/* The left panel carries the practice. Tinted, so the two halves read as
   two halves rather than as one long card with a rule across it. */
.gate-aside {
    background: var(--deep-soft); border-bottom: 1px solid var(--line);
    padding: 2rem 1.6rem 1.6rem;
    display: flex; flex-direction: column; gap: 1.4rem;
    align-items: center; justify-content: center; text-align: center;
}
@media (min-width: 46rem) {
    .gate-aside { border-bottom: 0; border-right: 1px solid var(--line); }
}

.gate-main { padding: 2rem 1.8rem 1.4rem; display: flex; flex-direction: column; }

.gate-brand { margin: 0; }
/* The mark is roughly square and carries no words, so it wants to be smaller
   than the old wide lockup did — at 15rem it dominated the card. */
.gate-logo { display: block; margin: 0 auto; max-width: 7.5rem; width: 100%; height: auto; }
.gate-practice {
    margin: .8rem 0 0; font-size: 1.05rem; font-weight: 700;
    letter-spacing: -.01em; line-height: 1.25;
}
.gate-role { margin: .15rem 0 0; font-size: .78rem; color: var(--ink-faint); }

/* The accreditation badge. Small on purpose: it is a credential, not the
   brand, and the eye should reach the sign-in form first. */
.gate-badge { margin: 0; }
.gate-badge img { display: block; margin: 0 auto; width: auto; height: 4.6rem; }
.gate-badge-note {
    margin: .5rem 0 0; font-size: .68rem; line-height: 1.45;
    color: var(--ink-faint); letter-spacing: .01em;
}
.gate-brand strong { display: block; font-size: 1.25rem; }
.gate-brand small { color: var(--ink-faint); }

/* Language sits at the top of the panel it affects, out of the way of the
   form, rather than adding another row to the bottom of the card.
   align-self, not display:flex — the switch is an inline-flex pill, and
   making it a block flex container stretched its border across the whole
   panel with the two words stranded at one end. */
.gate-lang { margin: 0 0 1.4rem; align-self: flex-end; }

.gate-note { font-size: .82rem; color: var(--ink-faint); line-height: 1.55; }
.gate-title { font-size: 1.1rem; margin: 0 0 .8rem; letter-spacing: -.01em; }

/* A phone has no room for the badge blurb above the password box, so on the
   narrowest screens the panel keeps the mark and the name and nothing else. */
@media (max-width: 30rem) {
    .gate { padding: .75rem; }
    .gate-aside { padding: 1.4rem 1.2rem 1.2rem; gap: 1rem; }
    .gate-main { padding: 1.4rem 1.2rem 1rem; }
    .gate-logo { max-width: 5.5rem; }
    .gate-badge img { height: 3.4rem; }
    .gate-badge-note { display: none; }
}

/* Attribution. Quiet enough to ignore while working, present on every page. */
.app-foot {
    margin: 3rem 0 0; padding-top: 1.2rem;
    border-top: 1px solid var(--line);
    font-size: .74rem; line-height: 1.6;
    color: var(--ink-faint); text-align: center;
}
/* Pushed to the foot of the right panel, so the card has a straight bottom
   edge whichever of the three gate pages is showing. */
.gate-foot { margin: auto 0 0; padding-top: 1.2rem; }

/* Her practice details, above the donation line. Slightly darker than the
   rest of the footer, because this is the part somebody might actually need
   to read off the screen. */
.app-practice {
    margin: 0 0 .5rem;
    color: var(--ink-soft);
    max-width: 46rem;
    margin-inline: auto;
}
/* Quiet, but present on every screen: the one place to check whether an
   update actually landed. */
.app-build { font-family: ui-monospace, Menlo, Consolas, monospace; font-size: .68rem; opacity: .75; }
@media print { .app-foot { display: none; } }

/* Show/hide on password boxes. The button sits inside the field's own box,
   so the input keeps its full width and nothing shifts when it appears. */
.pw { position: relative; display: block; }
.pw > input { width: 100%; padding-right: 2.9rem; }
.pw-eye {
    position: absolute; top: 50%; right: .5rem; transform: translateY(-50%);
    display: grid; place-items: center;
    width: 2rem; height: 2rem; padding: 0;
    border: 0; border-radius: 7px; background: transparent;
    color: var(--ink-faint); cursor: pointer;
}
.pw-eye:hover { color: var(--ink); background: var(--surface-sunk, rgba(127,127,127,.12)); }
.pw-eye:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* ==========================================================================
   Print
   ========================================================================== */

.sheet { max-width: 48rem; margin: 0 auto; padding: 2rem 1.5rem 4rem; }
.sheet-toolbar { display: flex; gap: .5rem; margin-bottom: 1.5rem; }
.sheet-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 1rem; border-bottom: 2px solid var(--ink); padding-bottom: .7rem; margin-bottom: 1.3rem; }
.sheet-head h1 { margin: 0; font-size: 1.4rem; }
.sheet-meta { margin: .2rem 0 0; color: var(--ink-soft); font-size: .85rem; }
.sheet-mark { font-size: .8rem; color: var(--ink-faint); text-align: right; }
.sheet-logo { display: block; margin-left: auto; margin-bottom: .35rem; max-width: 9.5rem; height: auto; }
.sheet-foot { margin-top: 2.5rem; padding-top: .7rem; border-top: 1px solid var(--line); font-size: .74rem; color: var(--ink-faint); }
.sheet section { margin-bottom: 1.4rem; page-break-inside: avoid; }
.sheet h2 { font-size: 1.02rem; border-bottom: 1px solid var(--line); padding-bottom: .25rem; }
.sheet dl { display: grid; grid-template-columns: 10rem 1fr; gap: .3rem .8rem; margin: 0; font-size: .9rem; }
.sheet dt { color: var(--ink-soft); font-weight: 600; }
.sheet dd { margin: 0; }
.writein { border-bottom: 1px solid var(--line); height: 1.5rem; margin-bottom: .4rem; }

@media print {
    :root { --bg:#fff; --surface:#fff; --ink:#000; --ink-soft:#333; --ink-faint:#555; --line:#bbb; --line-soft:#ddd; --accent:#444; --accent-soft:#f2f2f2; --accent-ink:#000; }
    body { background: #fff; font-size: 11.5pt; }
    .no-print, .topbar, .sidenav, .sheet-toolbar { display: none !important; }
    .sheet { padding: 0; max-width: none; }
    .card { box-shadow: none; border: 1px solid #ccc; break-inside: avoid; }
    a { color: #000; text-decoration: none; }
    .verse-block { font-size: 11pt; }

    /* Browsers drop background colour when printing, which would leave every
       bar blank. These bars are the only place a fill carries meaning, so ask
       for them back — and keep the numbers beside them either way. */
    .bars-track, .bars-fill, .trend-bar {
        -webkit-print-color-adjust: exact;
        print-color-adjust: exact;
    }
    .bars-fill, .trend-bar { background: #444 !important; }
    .bars-track { background: #e8e8e8 !important; }
    .trend-table { display: none; }
}

@media (prefers-reduced-motion: reduce) {
    * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* ==========================================================================
   Touch

   Keyed to the pointer rather than the width, because a tablet in landscape is
   1180px wide and still driven by a finger. A cursor lands where it is aimed;
   a fingertip covers about 9mm, so anything smaller than roughly 44px is a
   target she will miss and then blame herself for.
   ========================================================================== */
/* Two triggers for the same thing, on purpose.

   The width goes up to 1200px rather than stopping at the 860px layout break,
   because a tablet in landscape is around 1024–1194px and is still driven by a
   finger — that is the most likely way this app is held, and it would
   otherwise get desktop-sized hit areas. `pointer: coarse` then catches
   anything larger still.

   The cost is a slightly chunkier toolbar for someone using a mouse in a
   narrow laptop window. That is the right way round: a missed tap on a delete
   button costs more than a few pixels of padding ever will. */
@media (max-width: 1200px), (pointer: coarse) {
    .btn, button.btn, a.btn { padding: .6rem 1rem; }
    .btn-sm { padding: .5rem .8rem; font-size: .82rem; }

    /* The ⋯ button opens a panel that deletes things. It is the last control
       in the app that should be fiddly to hit. */
    .tools > summary { min-width: 2.75rem; min-height: 2.75rem; }

    .sidenav a { padding: .7rem .8rem; }
    .item { padding: .85rem .3rem; }
    .tabs a { padding: .6rem 1rem; }
    .icon-link { width: 2.6rem; height: 2.6rem; }
    .vault-pill { padding: .55rem .8rem; }
    .langswitch button { padding: .55rem .75rem; }
    .passage-tools .btn { padding: .55rem .75rem; }
    .topsearch input { padding: .6rem .75rem; }
    /* The eye that reveals a password: tapped most often on a phone, where a
       long vault passphrase is easiest to mistype. */
    .pw-eye { width: 2.5rem; height: 2.5rem; }
    .dictate-mic { padding: .5rem .8rem; }
    /* Padding alone leaves these at 33px: the type inside is deliberately
       tiny, so the box has to be told a floor of its own. */
    .dictate-lang button { padding: .5rem .8rem; min-height: 2.4rem; }
    .brand-mark { width: 40px; height: 40px; }

    /* The quiet secondary links — "Meer →", "Wys as tabel", a topic chip.
       They are small by design; on a touch screen they still need somewhere
       to land, so the padding grows even though the type does not. */
    .card-head .tiny, .trend-table > summary, a.tiny { padding: .55rem 0; display: inline-block; }
    .topic-chip { padding: .5rem .75rem; }

    /* Safari on iOS zooms the whole page when a field smaller than 16px takes
       focus, and never zooms back out. Sixteen pixels costs nothing and stops
       the page jumping every time she taps a box. */
    input[type=text], input[type=email], input[type=tel], input[type=password], input[type=date],
    input[type=datetime-local], input[type=number], input[type=search],
    input[type=time], select, textarea {
        font-size: 16px;
    }
}

/* Nothing may push the page sideways. Deliberately not solved with
   `overflow-x: hidden` on the body: that hides the symptom, breaks the sticky
   side column, and can crop a panel that opens near an edge. Each thing that
   overflows is given a width it may fall below instead — see the date inputs
   above — and anything genuinely wider than a phone scrolls inside its own
   box. */
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
