/* ============================================================
   TRIP DIARY — Try Swiss Knife
   Chrome (header, menu, footer, modals, help section) follows the
   platform standard and is derived from home-maker-diary.
   The diary body below it is this tool's own: warm paper, a ruled
   page, and a contents rail that is also the editing surface.

   Fonts (Gentium Book Plus + Caveat) are loaded from Google Fonts in
   index.html, exactly as the mockup does. Only --font-serif and
   --font-hand below refer to them; the chrome stays on the system
   sans stack, so the mockup's Inter is deliberately not loaded.
   ============================================================ */

:root {
    /* Platform chrome tokens */
    --color-primary: #003d5c;
    --color-accent: #00a8e8;
    --color-accent-hover: #0096c7;
    --color-white: #ffffff;
    --color-background: #f5f7fa;
    --color-border: #e0e6ed;
    --color-text-dark: #1a1a2e;
    --color-text-medium: #555f6d;
    --color-text-light: #8a95a3;
    --color-error: #ef4444;
    --color-danger-light: #fef2f2;

    /* Diary tokens */
    --paper: #fdfbf5;
    --paper-edge: #ece5d3;
    --desk: #f3efe4;
    --ink: #2b2b2b;
    --ink-soft: #6a6a63;
    /* Ruling and margin rule, at the strength the paper draws them. They are
       background layers, which carry their own alpha — there is no opacity to
       set, so the alpha is baked into the token. */
    --rule-ink: rgba(220, 214, 196, 0.28);
    --margin-ink: rgba(217, 168, 154, 0.55);
    --diary-accent: #8a6f4e;
    --diary-accent-soft: #f3ede0;
    /* Destructive, in the diary's own register. Platform --color-error (#ef4444)
       is a screen red and reads as a browser warning dropped on the paper; this
       is the oxblood of an ink correction. */
    --diary-danger: #9c3b2e;
    --diary-danger-soft: #f8ece7;

    --shadow-sm: 0 1px 3px rgba(0,0,0,0.06);
    --shadow-md: 0 4px 12px rgba(0,0,0,0.09);
    --shadow-lg: 0 8px 24px rgba(0,0,0,0.13);
    --paper-shadow: 0 1px 2px rgba(60,50,30,.08), 0 8px 24px rgba(60,50,30,.10);

    --radius-sm: 4px;
    --radius-md: 8px;
    --radius-lg: 12px;
    --radius-xl: 16px;

    --font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
    /* The two faces from the mockup, loaded from Google Fonts in index.html.
       Georgia is the fallback on purpose: it is the closest widely-installed
       serif, so the page stays readable and barely shifts if the fonts are slow. */
    --font-serif: 'Gentium Book Plus', Georgia, 'Iowan Old Style', 'Palatino Linotype', serif;
    /* The diary's own handwriting — captions, invitations, the marginal notes.
       Nothing structural is set in it; it never has to be read at speed. */
    --font-hand: 'Caveat', 'Segoe Script', 'Bradley Hand', cursive;
}

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

body {
    font-family: var(--font);
    background: var(--desk);
    min-height: 100vh;
    color: var(--color-text-dark);
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
    padding-bottom: env(safe-area-inset-bottom);
}

.container {
    width: 100%;
    max-width: 1200px;
    margin: 0 auto;
    padding: 16px 1.5rem 24px;
}

.hidden { display: none !important; }

/* The page's H1 is clip-hidden and keyword-bearing. The visible entry-screen
   heading is translated, so on FR/DE/ES it carries no English keyword at all —
   and it sits below "Continue your trip diary" in the markup, which would open
   the heading tree on an h2. Platform standard, same as allergy-diary. */
.seo-h1 {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: 0;
    overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}

/* ═══════════════════════════════════════════
   HEADER
═══════════════════════════════════════════ */
.header {
    width: 100%;
    background: var(--color-white);
    border-bottom: 1px solid var(--color-border);
    position: sticky;
    top: 0;
    z-index: 1000;
    box-shadow: 0 2px 4px rgba(0,0,0,0.05);
}

.header-inner {
    max-width: 1200px;
    margin: 0 auto;
    padding: 0.5rem 1.5rem;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
}

.header-left { display: flex; align-items: center; gap: 0.75rem; flex-shrink: 0; }

.header-logo-link { display: flex; align-items: center; text-decoration: none; transition: opacity 0.2s; }
.header-logo-link:hover { opacity: 0.85; }

.logo-image { height: 36px; width: auto; display: block; }

.tool-name-btn {
    font-size: 1.5rem;
    font-weight: 600;
    color: #1a2332;
    white-space: nowrap;
    line-height: 1.2;
    background: none;
    border: none;
    padding: 0;
    cursor: pointer;
    font-family: inherit;
    transition: color 0.15s;
}

.tool-name-btn:hover { color: var(--color-accent); }

.header-icons { display: flex; align-items: center; gap: 8px; flex-shrink: 0; position: relative; }

.header-icon-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px; height: 40px;
    padding: 0;
    background: var(--color-white);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: all 0.2s;
    color: var(--color-text-medium);
    font-family: inherit;
}
.header-icon-btn:hover {
    border-color: var(--color-accent);
    background: var(--color-background);
    color: var(--color-accent);
}
.header-icon-btn svg { width: 20px; height: 20px; }

.lang-short { font-size: 0.875rem; font-weight: 600; color: var(--color-text-dark); letter-spacing: 0.02em; }
.header-icon-btn:hover .lang-short { color: var(--color-accent); }

/* ─── Language Selector — i18n.js toggles .active on #languageDropdown ─── */
.language-selector { position: relative; }

.language-dropdown {
    display: none;
    position: absolute;
    right: 0;
    top: calc(100% + 6px);
    background: var(--color-white);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-md);
    min-width: 140px;
    z-index: 1100;
    overflow: hidden;
}
.language-dropdown.active { display: block; }

.lang-option {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    width: 100%;
    padding: 0.6rem 1rem;
    background: none;
    border: none;
    font-size: 0.875rem;
    cursor: pointer;
    color: var(--color-text-dark);
    transition: background 0.15s;
    font-family: inherit;
}
.lang-option:hover { background: var(--color-background); }
.lang-option.active { background: rgba(0,168,232,0.08); color: var(--color-accent); }
.lang-check { font-size: 0.75rem; opacity: 0; transition: opacity 0.15s; }
.lang-option.active .lang-check { opacity: 1; }

/* ─── Menu Button ─── */
.menu-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px; height: 40px;
    padding: 0;
    background: var(--color-white);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: all 0.2s;
    color: var(--color-text-medium);
}
.menu-btn:hover { border-color: var(--color-accent); background: var(--color-background); color: var(--color-accent); }

/* ═══════════════════════════════════════════
   MENU OVERLAY
   Geometry (position, width, height cap, scrolling, transition) comes from
   /shared/tsk-menu.css. Only this tool's look belongs below.
═══════════════════════════════════════════ */


.menu-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 0.85rem;
    gap: 8px;
}
.menu-header h3 { margin: 0; color: var(--color-text-dark); font-size: 1.1rem; }

/* Kept outside any overflow scroller, or the dropdown would be clipped */
.menu-header-right { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }

.close-menu {
    background: var(--color-background);
    border: 1px solid var(--color-border);
    font-size: 1.25rem;
    color: var(--color-text-medium);
    cursor: pointer;
    width: 40px; height: 40px;
    display: flex; align-items: center; justify-content: center;
    border-radius: var(--radius-md);
    line-height: 1;
    flex-shrink: 0;
    transition: all 0.15s;
}
.close-menu:hover { background: #fee2e2; color: var(--color-error); border-color: #fca5a5; }

.menu-action {
    width: 100%;
    background: var(--color-background);
    border: 1px solid var(--color-border);
    padding: 11px 14px;
    border-radius: var(--radius-lg);
    margin-bottom: 8px;
    cursor: pointer;
    transition: all 0.2s;
    display: flex;
    align-items: center;
    gap: 12px;
    font-size: 0.95rem;
    color: var(--color-text-dark);
    font-weight: 500;
    text-align: left;
    font-family: inherit;
}
.menu-action:hover { background: var(--color-white); border-color: var(--color-accent); transform: translateY(-1px); box-shadow: var(--shadow-sm); }
.menu-action.danger { color: var(--color-error); border-color: #fca5a5; }
.menu-action.danger:hover { background: var(--color-danger-light); border-color: var(--color-error); }
/* The two rows that do something to the diary itself rather than to a file, sitting
   at the top of the menu. Marked the way .danger is — colour and border, nothing
   heavier — so the menu reads as three registers: the diary's own work, file
   plumbing, then the destructive pair.
   The blue is a darkened step of --color-accent (#00a8e8), not --color-primary
   (#003d5c): the navy is so dark it reads as black next to --color-text-dark and
   marks nothing. The accent itself is too pale to pass AA on this background, so
   the row takes the step between them — 4.5:1 on --color-background, and visibly blue. */
.menu-action.feature { color: #0077b6; border-color: #9ccbe4; }
.menu-action.feature:hover { background: #eaf6fc; border-color: #0077b6; }

.action-icon { font-size: 1.35rem; flex-shrink: 0; }
.action-content { display: flex; flex-direction: column; gap: 1px; flex: 1; }
.action-hint { font-size: 0.72rem; color: var(--color-text-light); font-weight: 400; font-style: italic; }

.menu-divider { height: 1px; background: var(--color-border); margin: 2px 0 10px; }

/* Unsaved-changes dot — tsk-cloud.js ships the .cloud-dirty styling */

/* ═══════════════════════════════════════════
   INFO BANNER
═══════════════════════════════════════════ */
/* A note laid on the desk, not a browser alert. The platform banner this was
   copied from is Material sky blue on white — right for contribution/, whose
   chrome is blue, but on warm paper it is the one cool object on the page. The
   same reasoning that produced --diary-danger applies: the tool has its own
   register and the banner belongs in it.

   It is paper, like every other card, and is told apart from the card below it
   by the margin rule down its left edge rather than by a different fill —
   --diary-accent-soft would have been the obvious tint, but at #f3ede0 it is
   four values off --desk and would have vanished into the background. */
/* Tinted stock rather than --paper. At paper tone the notice was the lightest
   thing on the desk and slid past the eye; this reads as a slip that was laid
   down separately. --diary-accent keeps the margin edge — the brown ink is
   already the right colour for it — just drawn 4px so it carries the darker
   fill. --ink-soft would fall to 4.1:1 on this stock, so the body text steps
   down to #5c584f (5.4:1, marginally better than it was on paper). */
.info-banner {
    background: #E9E0C9;
    border: 1px solid #DDD1B4;
    border-left: 4px solid var(--diary-accent);
    border-radius: var(--radius-md);
    padding: 12px 16px;
    display: flex;
    align-items: center;
    gap: 12px;
    box-shadow: 0 2px 6px rgba(60, 50, 30, 0.09);
    margin-bottom: 20px;
}
.info-icon { font-size: 1.3rem; flex-shrink: 0; }
.info-text { flex: 1; color: #5c584f; font-size: 0.9rem; line-height: 1.5; }
.info-text strong { color: var(--ink); font-weight: 600; }
.info-close {
    background: none; border: none;
    color: #5c584f;
    font-size: 1.5rem; font-weight: bold;
    cursor: pointer; padding: 0;
    width: 24px; height: 24px;
    display: flex; align-items: center; justify-content: center;
    border-radius: 4px;
    transition: all 0.2s ease;
    flex-shrink: 0; line-height: 1; margin-left: auto;
}
.info-close:hover { background: rgba(138, 111, 78, 0.16); color: var(--diary-accent); }

/* ═══════════════════════════════════════════
   BUTTONS & FORMS (shared)
═══════════════════════════════════════════ */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 0.55rem 1.1rem;
    border-radius: var(--radius-md);
    font-family: var(--font);
    font-size: 0.9rem;
    font-weight: 600;
    cursor: pointer;
    border: 2px solid transparent;
    transition: all 0.2s;
    text-decoration: none;
    white-space: nowrap;
}
.btn:disabled { opacity: 0.45; cursor: not-allowed; }
.btn-block { width: 100%; }
.btn-sm { padding: 0.4rem 0.9rem; font-size: 0.82rem; }
.btn-primary { background: var(--color-accent); color: var(--color-white); border-color: var(--color-accent); }
.btn-primary:hover:not(:disabled) { background: var(--color-accent-hover); border-color: var(--color-accent-hover); }
.btn-outline { background: var(--color-white); color: var(--color-text-dark); border-color: var(--color-border); }
.btn-outline:hover:not(:disabled) { border-color: var(--color-accent); color: var(--color-accent); }
.btn-danger { background: var(--color-error); color: var(--color-white); border-color: var(--color-error); }
.btn-danger:hover:not(:disabled) { background: #dc2626; border-color: #dc2626; }

.form-group { margin-bottom: 0.9rem; }
.form-group:last-child { margin-bottom: 0; }
.form-group label {
    display: block;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--color-text-medium);
    margin-bottom: 5px;
}
.form-input, .form-select, .form-textarea,
input[type="text"], input[type="url"], input[type="date"], input[type="number"], select {
    width: 100%;
    height: 40px;
    padding: 0 12px;
    border: 1.5px solid var(--color-border);
    border-radius: var(--radius-md);
    font-family: var(--font);
    font-size: 0.95rem;
    color: var(--color-text-dark);
    background: var(--color-white);
    transition: border-color 0.2s;
    outline: none;
}
.form-textarea, textarea {
    width: 100%;
    height: auto;
    min-height: 80px;
    padding: 10px 12px;
    resize: vertical;
    line-height: 1.5;
    border: 1.5px solid var(--color-border);
    border-radius: var(--radius-md);
    font-family: var(--font);
    font-size: 0.95rem;
    color: var(--color-text-dark);
    background: var(--color-white);
    outline: none;
}
.form-input:focus, .form-select:focus, .form-textarea:focus,
input:focus, select:focus, textarea:focus {
    border-color: var(--color-accent);
    box-shadow: 0 0 0 3px rgba(0,168,232,0.12);
}
.form-select, select { cursor: pointer; appearance: auto; }
.field-hint { font-size: 0.75rem; color: var(--color-text-light); margin-top: 5px; line-height: 1.45; }

.radio-group { display: flex; flex-wrap: wrap; gap: 8px; }
.radio-group > label {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 8px 14px;
    border: 1.5px solid var(--color-border);
    border-radius: 100px;
    cursor: pointer;
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--color-text-medium);
    background: var(--color-white);
    margin-bottom: 0;
    transition: all 0.15s;
}
.radio-group > label:hover { border-color: var(--color-accent); }
.radio-group input[type="radio"] { width: auto; height: auto; accent-color: var(--color-accent); margin: 0; }
.radio-group > label:has(input:checked) { border-color: var(--color-accent); background: rgba(0,168,232,0.07); color: var(--color-primary); }

.checkbox-label {
    display: flex;
    align-items: flex-start;
    gap: 9px;
    font-size: 0.85rem;
    color: var(--color-text-medium);
    cursor: pointer;
    line-height: 1.45;
    margin: 10px 0;
}
.checkbox-label input[type="checkbox"] { width: auto; height: auto; margin-top: 2px; accent-color: var(--color-accent); flex-shrink: 0; }

/* ═══════════════════════════════════════════
   SETUP / ENTRY SCREEN
═══════════════════════════════════════════ */
/* One card, two zones — the signed-off design in
   `claude-share/Trip planner redesign/Trip Diary Home.dc.html`.

   The card carries no padding of its own: the hero and the tinted band below it
   pad themselves, so the tint can run edge to edge. `overflow: hidden` is what
   keeps the band's square corners inside the card's rounded ones.

   Written as `.card.setup-card` on purpose: the shared `.card` rule below sets
   `padding: 22px` and the ≤480 block sets 16px, both of which would win on
   source order against a single class. The zero padding is structural, not a
   tweak — lose it and the band stops reaching the card edges.

   The illustration is a feathered PNG: never give it a frame, a mount or a
   shadow. The soft edge dissolving into the paper is the entire effect, and a
   hard rectangle around it would undo it. */
.card.setup-card {
    max-width: 1160px;
    margin: 4px auto 0;
    padding: 0;
    overflow: hidden;
    border-radius: var(--radius-xl);
}

/* Zone 1. The picture takes the left column at full height, the words and the
   start form take the right — a slightly wider 1.1fr, because that column
   carries everything with a line length to protect.

   `align-items: center` is right *here* and was wrong in the layouts that came
   before it: the two columns are close enough in height that centring reads as
   composition rather than as a gap. It only misbehaves when a short column sits
   beside a much taller one.

   No areas and no source reordering — the <picture> is first in the markup and
   first in the grid. That is also what makes the phone float work below 900px,
   where a float can only affect what follows it. */
.setup-hero {
    display: grid;
    grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
    gap: 40px;
    align-items: center;
    padding: 38px 40px 34px;
}
.setup-main { min-width: 0; }
.setup-head { margin-bottom: 26px; }
.hero-art { display: block; width: 100%; max-width: 440px; justify-self: center; }
.hero-words { min-width: 0; }
/* The head already carries the gap; the form does not add a second one. */
.hero-words > :first-child { margin-top: 0; }
.hero-art img {
    display: block;
    width: 100%;
    height: auto;
    user-select: none;
    pointer-events: none;
}

/* One orchestrated moment on load: the picture settles, the words follow.
   The global prefers-reduced-motion rule already flattens both. */
@keyframes settle {
    from { opacity: 0; transform: translateY(10px); }
    to   { opacity: 1; transform: none; }
}
.hero-art  { animation: settle 0.5s ease both; }
.setup-head { animation: settle 0.5s 0.08s ease both; }

/* The mockup's display sizes. The kicker is the page's voice, not its title —
   it stays a <p> and the <h1> is the start heading below it, which is why this
   is set here rather than on a heading selector. */
.setup-kicker {
    font-family: var(--font-serif);
    font-style: italic;
    font-size: 2.35rem;
    letter-spacing: -0.01em;
    color: var(--ink);
    line-height: 1.15;
}
.setup-lede {
    font-size: 1.05rem;
    color: var(--color-text-medium);
    line-height: 1.65;
    margin-top: 16px;
    max-width: 34em;
    text-wrap: pretty;
}

/* The four words painted on the signpost in the illustration, in the diary's
   own hand. The page and the picture say the same thing — which is why this
   line is decorative to a screen reader and marked aria-hidden. */
.signpost {
    margin-top: 18px;
    font-family: var(--font-hand);
    font-weight: 600;
    font-size: 1.65rem;
    line-height: 1.4;
    color: var(--diary-accent);
}
/* The spans are separated by real whitespace in the markup, which is what
   gives the line somewhere to break. The separator only needs the gap on its
   right — the collapsed space supplies the one on its left. */
.signpost span + span::before { content: '·'; margin-right: 7px; opacity: 0.45; }

.setup-start { margin-top: 24px; }

/* Cards are paper on the desk — the same relationship the diary page itself
   has, so the entry screen and the tool read as one material. */
.card {
    background: var(--paper);
    border: 1px solid var(--paper-edge);
    border-radius: var(--radius-lg);
    padding: 22px;
    box-shadow: var(--paper-shadow);
}
/* Section headings inside a card. The entry screen's start heading is one of
   them: the page's one <h1> is the clip-hidden SEO heading in <body>, so the
   start heading is an h2 and this rule already reaches it. */
.card h2 {
    font-family: var(--font-serif);
    font-size: 1.2rem;
    font-weight: 700;
    color: var(--ink);
    margin-bottom: 16px;
    padding-bottom: 10px;
    border-bottom: 1px solid var(--paper-edge);
}
/* The entry screen's two section headings carry the hero's scale. The rule
   above is sized for the tool's dialogs and panels, which sit at reading size —
   this has to come after it, not before, or it loses on source order. */
.setup-start h2,
.setup-continue h2 { font-size: 1.4rem; padding-bottom: 14px; }

.sample-hint { font-size: 0.78rem; color: var(--color-text-light); margin-top: 7px; }
.sample-link { color: var(--diary-accent); text-decoration: none; font-weight: 600; }
.sample-link:hover { text-decoration: underline; }
.sample-sep { margin: 0 4px; color: var(--color-border); }

.date-input-group { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 16px; }

.setup-note {
    font-family: var(--font-serif);
    font-size: 0.9rem;
    color: var(--color-text-light);
    font-style: italic;
    margin-top: 14px;
    text-align: center;
}

/* Zone 2. Bringing something with you — a file or a plan. A tinted band across
   the foot of the same card rather than a separate block: it reads as the other
   half of one surface, and because .setup-card has no padding the tint runs the
   full width. It never competes with starting — the one call to action is up in
   the hero — but it is also not below the fold, which is where it was when it
   lived on the desk under the card.

   Two cards side by side, each ending on its button: the buttons line up
   because the description above them is allowed to be different lengths. Import
   is the left one, and it is left because it is first in the markup. */
.setup-have {
    padding: 28px 40px 30px;
    background: var(--diary-accent-soft);
    border-top: 1px solid var(--paper-edge);
}
.have-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 14px;
    flex-wrap: wrap;
    margin-bottom: 16px;
    padding: 0 2px;
}
.have-title {
    font-family: var(--font);
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ink-soft);
}
.have-note { font-size: 0.83rem; color: var(--color-text-light); }

.have-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px; }
.have-card {
    display: flex;
    flex-direction: column;
    /* Paper, not white. These two sit inside the same card the hero does, and a
       pure #fff panel on a warm off-white page reads as a UI widget dropped onto
       the paper rather than part of it. The tinted band behind them is what
       separates them from the card; the border does the rest. */
    background: var(--paper);
    border: 1px solid var(--paper-edge);
    border-radius: 14px;
    padding: 20px 24px 22px;
    transition: box-shadow 0.15s;
}
.have-card:hover { box-shadow: 0 8px 18px rgba(60,50,30,0.08); }
.have-card-head { display: flex; align-items: center; gap: 10px; margin-bottom: 7px; }
.have-icon { font-size: 1.25rem; flex-shrink: 0; line-height: 1; }
.have-card-title { font-size: 1.05rem; font-weight: 700; color: var(--ink); }
.have-badge {
    margin-left: auto;
    flex-shrink: 0;
    padding: 3px 10px;
    border-radius: 100px;
    background: var(--diary-accent-soft);
    color: var(--diary-accent);
    font-size: 0.64rem;
    font-weight: 700;
    letter-spacing: 0.09em;
    text-transform: uppercase;
}
.have-card-sub { font-size: 0.9rem; color: var(--color-text-medium); line-height: 1.55; }
.have-card-sub:empty { display: none; }
/* The button sits at the foot of the card whatever the copy above it does. */
.have-card .checkbox-label { margin-top: 12px; }
.have-card > .btn-paper-quiet,
.have-card > .btn-paper-strong,
.have-card #import-ready { margin-top: auto; padding-top: 14px; }
.have-card #import-ready > .btn-paper-strong,
.have-card #import-ready > .btn-paper-quiet { margin-top: 12px; }
.have-card #import-empty { margin-top: auto; padding-top: 10px; }

/* The one call to action on the page carries more weight than the dialog
   primaries the family is sized for. */
#create-btn { font-size: 1.02rem; padding: 15px 24px; margin-top: 6px; }
/* The two ways in are secondary to it, but still the action of their own card. */
.have-card .btn-paper-strong,
.have-card .btn-paper-quiet { font-size: 0.88rem; padding: 12px 20px; }

/* The entry screen's forms are paper too — warm fields, sepia focus, no
   platform blue anywhere the eye can reach it. The fields are also a size up
   from the tool's dialogs: this is the one form a visitor meets cold. */
#setup-section .form-group { margin-bottom: 1.1rem; }
#setup-section .form-group label { color: var(--ink-soft); font-size: 0.9rem; }
#setup-section input[type="text"],
#setup-section input[type="date"],
#setup-section input[type="number"],
#setup-section select {
    height: 48px;
    padding: 0 16px;
    font-size: 1rem;
    border-radius: 10px;
    background: rgba(255,255,255,0.62);
    border-color: #ddd4bd;
    color: var(--ink);
}
#setup-section input[type="text"]:focus,
#setup-section input[type="date"]:focus,
#setup-section input[type="number"]:focus,
#setup-section select:focus {
    border-color: var(--diary-accent);
    box-shadow: 0 0 0 3px rgba(138,111,78,0.10);
}
#setup-section input[type="radio"],
#setup-section input[type="checkbox"] { accent-color: var(--diary-accent); }
/* Two pills sharing the row, as the mockup draws them — not two chips hugging
   their labels. They sit directly above two full-width fields, so anything
   narrower reads as a different kind of control. */
#setup-section .radio-group { gap: 12px; flex-wrap: nowrap; }
#setup-section .radio-group > label {
    flex: 1;
    justify-content: center;
    padding: 12px 14px;
    font-size: 0.95rem;
    background: rgba(255,255,255,0.62);
    border-color: #ddd4bd;
    color: var(--ink-soft);
}
#setup-section .radio-group > label:hover { border-color: var(--diary-accent); }
#setup-section .radio-group > label:has(input:checked) {
    border-color: var(--diary-accent);
    background: var(--diary-accent-soft);
    color: var(--diary-accent);
}

/* A diary already on this device, above the start form: someone mid-way
   through writing came back to carry on, not to begin again. */
.setup-continue { margin-top: 20px; }
.saved-card {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 14px;
    background: var(--diary-accent-soft);
    border: 1.5px solid #ded3bc;
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: all 0.15s;
}
.saved-card:hover { border-color: var(--diary-accent); box-shadow: var(--shadow-sm); }
.saved-info { flex: 1; min-width: 0; }
.saved-name { font-weight: 600; font-size: 0.95rem; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.saved-time { font-size: 0.75rem; color: var(--ink-soft); margin-top: 1px; }
.saved-delete {
    background: none; border: none;
    font-size: 1.3rem; line-height: 1;
    color: var(--color-text-light);
    cursor: pointer; padding: 0 4px;
    flex-shrink: 0;
}
.saved-delete:hover { color: var(--color-error); }

/* Last thing in the band, under both cards — it is about the browser not
   finding a saved diary, so it belongs with the ways of opening one. */
.cache-refresh-hint {
    margin-top: 18px;
    padding: 9px 11px;
    background: #fffbeb;
    border: 1px solid #fde68a;
    border-radius: var(--radius-sm);
    font-size: 0.72rem;
    color: #92400e;
    line-height: 1.5;
}
.cache-refresh-hint kbd {
    background: var(--color-white);
    border: 1px solid #fbbf24;
    border-radius: 3px;
    padding: 1px 4px;
    font-size: 0.68rem;
    font-family: ui-monospace, Menlo, monospace;
}

/* ═══════════════════════════════════════════
   THE DIARY — contents rail + one page
═══════════════════════════════════════════ */
.diary-shell {
    display: grid;
    grid-template-columns: 262px 1fr;
    gap: 22px;
    align-items: start;
}

/* ─── Contents rail. Also the editing surface: with no import there is
       nothing to click into, so creation has to live somewhere. ─── */
.toc {
    background: var(--color-white);
    border: 1px solid var(--paper-edge);
    border-radius: var(--radius-lg);
    padding: 6px;
    position: sticky;
    top: 74px;
    box-shadow: var(--paper-shadow);
}

.toc-head { padding: 10px 10px 9px; border-bottom: 1px solid #efeade; margin-bottom: 5px; position: relative; }
.toc-trip-row { display: flex; align-items: flex-start; gap: 4px; }
.toc-trip {
    font-family: var(--font-serif);
    font-size: 1rem;
    font-weight: 700;
    line-height: 1.25;
    color: var(--ink);
    flex: 1;
    min-width: 0;
    overflow-wrap: anywhere;
}
.toc-sub { font-size: 0.7rem; color: var(--ink-soft); margin-top: 3px; }
.toc-close { display: none; }

.toc-scroll { max-height: 58vh; overflow-y: auto; overscroll-behavior: contain; }

.toc-day { padding: 7px 9px; border-radius: 7px; cursor: pointer; }
.toc-day:hover { background: #faf8f2; }
.toc-day:hover .rowact { opacity: 1; }
.toc-day.current { background: var(--diary-accent-soft); }
.toc-day-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 7px; }
.toc-date { font-size: 0.8rem; font-weight: 600; color: var(--ink); }
.toc-place { font-size: 0.7rem; color: var(--ink-soft); margin-top: 1px; }
.toc-day-right { display: flex; align-items: center; gap: 2px; flex-shrink: 0; }
.toc-meta { font-size: 0.66rem; color: var(--ink-soft); margin-top: 3px; }

.dot { width: 7px; height: 7px; border-radius: 50%; flex: none; margin-top: 5px; }
.dot.filled { background: var(--diary-accent); }
.dot.empty { background: var(--color-white); border: 1.5px solid #cfc8b6; }

.toc-act {
    position: relative;
    padding: 4px 9px 4px 22px;
    font-size: 0.735rem;
    color: var(--ink-soft);
    display: flex;
    align-items: center;
    gap: 7px;
    cursor: pointer;
    border-radius: 6px;
}
.toc-act:hover { background: #faf8f2; color: var(--ink); }
.toc-act:hover .rowact { opacity: 1; }
.toc-act.current { background: var(--diary-accent-soft); color: var(--ink); font-weight: 500; }
.toc-act .dot { width: 5px; height: 5px; margin-top: 0; }
.toc-act .lbl { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* The grip lives in the row's own left indent, so showing it costs no layout —
   the label never shifts as the pointer crosses the list. */
.toc-grip {
    position: absolute;
    left: 6px;
    top: 50%;
    transform: translateY(-50%);
    font-size: 0.8rem;
    line-height: 1;
    color: #c3bba7;
    opacity: 0;
    transition: opacity 0.12s;
    cursor: grab;
}
.toc-act:hover .toc-grip { opacity: 1; }
.toc-act.dragging { opacity: 0.45; }
.toc-act.dragging .toc-grip { cursor: grabbing; }

/* An inset rule rather than a border: it marks the seam the moment will land in
   without moving the rows around it a pixel. */
.toc-act.drop-above { box-shadow: inset 0 2px 0 var(--diary-accent); }
.toc-act.drop-below { box-shadow: inset 0 -2px 0 var(--diary-accent); }

.rowact {
    opacity: 0;
    font-size: 0.72rem;
    color: #b0a894;
    padding: 2px 3px;
    background: none;
    border: none;
    cursor: pointer;
    transition: 0.12s;
    font-family: inherit;
    line-height: 1;
}
.rowact:hover { color: var(--diary-accent); }
.rowact:focus-visible { opacity: 1; outline: 2px solid var(--diary-accent); outline-offset: 1px; }
.toc-rename-trip { opacity: 0.55; }
.toc-rename-trip:hover { opacity: 1; }

/* The kebab holds its place while its menu is open, or the row it belongs to
   looks unrelated to the popup sitting under it. */
.rowact-menu { font-size: 0.95rem; padding: 1px 4px; letter-spacing: 0; }
.rowact[aria-expanded="true"] { opacity: 1; color: var(--diary-accent); }

/* ─── Row menu ───
   Body-mounted and fixed (see openRowMenu) because .toc-scroll clips. Paper
   card, so it reads as part of the contents rather than as browser chrome. */
.row-menu {
    position: fixed;
    z-index: 1300;
    min-width: 190px;
    padding: 5px;
    background: var(--paper);
    border: 1px solid var(--paper-edge);
    border-radius: var(--radius-md);
    box-shadow: 0 2px 4px rgba(60,50,30,0.10), 0 12px 28px rgba(60,50,30,0.18);
    animation: rowMenuIn 0.12s ease;
}
@keyframes rowMenuIn {
    from { opacity: 0; transform: translateY(-3px); }
    to   { opacity: 1; transform: none; }
}
.row-menu-item {
    display: flex;
    align-items: center;
    gap: 9px;
    width: 100%;
    padding: 7px 10px;
    font-family: var(--font);
    font-size: 0.8rem;
    color: var(--ink);
    background: none;
    border: none;
    border-radius: 6px;
    cursor: pointer;
    text-align: left;
    transition: background 0.12s, color 0.12s;
}
.row-menu-item:hover:not(:disabled) { background: var(--diary-accent-soft); color: var(--diary-accent); }
.row-menu-item:focus-visible { outline: 2px solid var(--diary-accent); outline-offset: -2px; }
.row-menu-item:disabled { opacity: 0.42; cursor: default; }
.row-menu-item.danger { color: var(--diary-danger); }

/* The destination list is as long as the trip, so it scrolls rather than
   running off the window. openRowMenu positions from offsetHeight, which the
   max-height keeps honest. */
.row-menu-days { max-height: 52vh; overflow-y: auto; overscroll-behavior: contain; }
.row-menu-days .row-menu-item { max-width: 280px; }
.row-menu-days .rm-ic { flex-shrink: 0; }
.row-menu-days .row-menu-item span:last-child {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.row-menu-item.danger:hover:not(:disabled) { background: var(--diary-danger-soft); color: var(--diary-danger); }
.rm-ic { width: 15px; text-align: center; font-size: 0.85rem; opacity: 0.85; flex-shrink: 0; }

.toc-addact {
    display: block;
    width: calc(100% - 22px);
    margin-left: 22px;
    padding: 3px 9px;
    font-family: var(--font-hand);
    font-size: 0.98rem;
    font-weight: 600;
    color: #b3aa93;
    cursor: pointer;
    border: none;
    background: none;
    border-radius: 6px;
    text-align: left;
}
.toc-addact:hover { color: var(--diary-accent); background: #faf8f2; }

.toc-foot {
    border-top: 1px solid #efeade;
    margin-top: 6px;
    padding: 8px 4px 4px;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.toc-btn {
    text-align: left;
    background: none;
    border: none;
    padding: 7px 8px;
    border-radius: 6px;
    font-size: 0.78rem;
    color: var(--ink-soft);
    cursor: pointer;
    font-family: inherit;
    display: flex;
    align-items: center;
    gap: 9px;
}
.toc-btn:hover { background: #faf8f2; color: var(--diary-accent); }
.toc-btn .ic { width: 15px; text-align: center; opacity: 0.75; }

/* Always-on local check — pure computation, instant, works offline */
.gaps { font-size: 0.68rem; color: var(--ink-soft); padding: 4px 9px 4px; line-height: 1.45; }

/* Mobile contents trigger */
.toc-open-btn {
    display: none;
    width: 100%;
    align-items: center;
    gap: 10px;
    padding: 10px 14px;
    margin-bottom: 12px;
    background: var(--color-white);
    border: 1px solid var(--paper-edge);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-sm);
    cursor: pointer;
    font-family: inherit;
    font-size: 0.88rem;
    color: var(--ink);
    text-align: left;
}
.toc-open-icon { font-size: 1rem; color: var(--diary-accent); }
.toc-open-label { font-weight: 600; }
.toc-open-where { color: var(--ink-soft); font-size: 0.78rem; margin-left: auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ─── The page ─── */
.page-wrap { min-width: 0; }

/* The corners hang off the frame, not the page, so they stay at the paper's
   bottom edge while the writing scrolls inside it. */
.page-frame { position: relative; }

/* The ruling and the red margin rule are the paper itself — background layers
   on .page, not overlay pseudo-elements. Two things follow, and both are the
   point: `local` attachment makes them span the whole scrolled height instead
   of stopping at the first screenful, and a background cannot be interrupted by
   anything laid out on top of it, so the margin rule runs unbroken past every
   moment, aside and photo. A real diary's margin does not stop and restart. */
.page {
    --margin-x: 42px;
    background-color: var(--paper);
    background-image:
        linear-gradient(to right,
            transparent var(--margin-x),
            var(--margin-ink) var(--margin-x),
            var(--margin-ink) calc(var(--margin-x) + 1px),
            transparent calc(var(--margin-x) + 1px)),
        repeating-linear-gradient(to bottom, transparent 0 31px, var(--rule-ink) 31px 32px);
    background-attachment: local, local;
    border: 1px solid var(--paper-edge);
    border-radius: 3px;
    padding: 40px 48px 64px 60px;
    box-shadow: var(--paper-shadow);
    position: relative;
    min-height: 620px;
    max-height: calc(100vh - 150px);
    overflow-y: auto;
    outline: none;
}
.page > * { position: relative; }

.page.turning { animation: pageTurn 0.18s ease; }
@keyframes pageTurn {
    from { opacity: 0.25; transform: translateX(var(--turn-from, 10px)); }
    to   { opacity: 1; transform: translateX(0); }
}

.date-line {
    font-family: var(--font-serif);
    font-style: italic;
    font-size: 1.55rem;
    color: var(--ink);
    margin-bottom: 2px;
    display: flex;
    align-items: baseline;
    gap: 8px;
    flex-wrap: wrap;
}
.place-line {
    font-size: 0.72rem;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--ink-soft);
    margin-bottom: 4px;
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
}
.place-line .plc-empty { font-style: italic; text-transform: none; letter-spacing: 0; opacity: 0.75; }

/* The only way into the places, once per page, on a line thin enough that
   hover is a poor place to hide it — so it keeps a low steady presence and
   comes up on hover, the way the trip rename does in the contents. The
   focus-visible reveal is repeated here because the base .rowact rule carries
   equal specificity and loses on order. */
.place-line .rowact {
    opacity: 0.5;
    font-size: 0.88rem;
    /* Boxed at 18px so it cannot outgrow the place line's own 18.4px height.
       A taller button here pushes the whole page down by a fraction of a rule,
       which is the one shift the ruled paper shows up immediately. */
    height: 18px;
    padding: 0 5px;
    display: inline-flex;
    align-items: center;
    border-radius: 6px;
}
.place-line:hover .rowact, .place-line .rowact:focus-visible { opacity: 1; }
.place-line .rowact:hover { background: var(--diary-accent-soft); }

.import-note {
    font-size: 0.72rem;
    color: var(--ink-soft);
    font-style: italic;
    margin: 12px 0 16px;
    padding-bottom: 10px;
    border-bottom: 1px solid #ece5d4;
}

/* Day narrative and activity prose are two registers and must look
   different, or the page becomes an undifferentiated wall. */
.prose {
    font-family: var(--font-serif);
    font-size: 1.04rem;
    line-height: 32px;
    color: var(--ink);
    margin: 18px 0 20px;
    white-space: normal;
}
.prose p { margin: 0 0 32px; }
.prose p:last-child { margin-bottom: 0; }
/* Done hands focus back to the writing. After a click that must be silent;
   after Enter on the button, :focus-visible earns the ring. */
.prose:focus { outline: none; }
.prose:focus-visible { outline: 2px solid var(--diary-accent); outline-offset: 4px; border-radius: 3px; }

/* 32px, matching the rules — not 30. A moment's writing is set smaller than the
   day's, but it is written on the same paper, and a 30px line against a 32px
   rule drifts 2px further off with every line: by the fourth it is a clear 8px
   adrift and the block visibly slides between the lines. The paragraph gap is
   one whole rule for the same reason. */
.act .prose { font-size: 0.97rem; line-height: 32px; margin: 6px 0 12px; }
.act .prose p { margin-bottom: 32px; }

/* "from your plan" aside — planning shorthand never mixes with what the
   user actually wrote. */
.plan-aside { margin: 14px 0 18px; }
.plan-aside-toggle {
    background: none;
    border: none;
    padding: 0;
    font-family: var(--font);
    font-size: 0.72rem;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: #b0a894;
    cursor: pointer;
}
.plan-aside-toggle:hover { color: var(--diary-accent); }
.plan-aside-body {
    margin-top: 8px;
    padding: 10px 14px;
    background: #f7f3e8;
    border-left: 3px solid #ded3bc;
    border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
    font-size: 0.82rem;
    line-height: 1.6;
    color: var(--ink-soft);
    white-space: pre-wrap;
}

/* A moment is a passage the writer started partway down the page, not a row in
   a tree — so it carries no vertical rule. What marks it is what marks it on
   real paper: an indent, and a change of hand. */
.act {
    margin: 0 0 30px;
    padding-left: 18px;
}
.act-head { display: flex; align-items: baseline; gap: 9px; margin-bottom: 4px; flex-wrap: wrap; }

/* The diary's own hand, underlined the way you underline a heading mid-page.
   Caveat's small x-height does the work the brief asks for: nominally larger
   than the day's prose, optically smaller — clearly a sub-head, still legible.
   The underline is the one flourish here; it replaces the rule that was. */
.act-title {
    font-family: var(--font-hand);
    font-weight: 700;
    font-size: 1.34rem;
    line-height: 1.25;
    color: var(--diary-accent);
    text-decoration: underline;
    text-decoration-color: rgba(138, 111, 78, 0.3);
    text-decoration-thickness: 1px;
    text-underline-offset: 6px;
}

/* Trailing, never leading. Set in the reading serif at a whisper so it reads
   as a note added beside the title rather than a label the moment sits under.
   No text-transform: German capitalises its nouns and lowercasing them here
   would be a spelling mistake, not a style. */
.act-slot {
    font-family: var(--font-serif);
    font-style: italic;
    font-size: 0.78rem;
    color: var(--ink-soft);
    opacity: 0.8;
    flex-shrink: 0;
}
.act-slot::before { content: '— '; opacity: 0.6; }
.act-actions { margin-left: auto; align-self: center; display: flex; gap: 3px; opacity: 0; transition: opacity 0.12s; }
.act:hover .act-actions, .act:focus-within .act-actions { opacity: 1; }
/* .rowact hides itself, and opacity does not inherit — revealing the container
   alone leaves the buttons at zero. The TOC rows carry the same pair of rules. */
.act:hover .rowact, .act:focus-within .rowact { opacity: 1; }

/* Sized against the 1.34rem title they sit beside, not against the contents
   rail: the rail is a dense list where 0.72rem glyphs are right, the page is
   open paper where they read as specks. The chip gives the hit area the row
   never had — the glyph itself was barely 11px of clickable target. */
.act-actions .rowact {
    /* 26px, not more: .act-head is as tall as its tallest child, and the title's
       line box is 26.8px (1.34rem × 1.25). A taller button grows the head and
       walks the whole moment off the ruled lines. */
    width: 26px;
    height: 26px;
    padding: 0;
    font-size: 1.02rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 8px;
}
.act-actions .rowact:hover { background: var(--diary-accent-soft); }

/* The day's media invitation. Quiet by design — it stands under the album on
   every page, so it must not compete with the writing above it. No border: the
   dashed box belongs to .addline and means "write here". */
.media-addline {
    font-family: var(--font-hand);
    font-size: 1.04rem;
    color: #a89e88;
    background: none;
    border: none;
    border-radius: 7px;
    /* Exactly one ruled line — 32px, no vertical margin. The paper's rules are a
       fixed 32px repeat, so anything sitting between the writing and the moments
       must consume a whole number of them or every line below it lands off the
       rule. Change the height and change it in multiples. */
    height: 32px;
    line-height: 32px;
    padding: 0 9px 0 6px;
    /* Two rules in total, not one. The 32px below is not decoration: this button
       stands between the album and whatever follows, whose 14px margins used to
       collapse into each other. Both now apply, so the block costs 14+32+32
       against the 14 it replaces — a clean 64, two whole rules. Changing this
       margin walks every line below off the paper. */
    margin: 0 0 32px;
    /* Block with a 32px line box rather than a centred flex row: centring puts
       the glyph in the middle of the band, where the prose around it rests its
       baseline on the rule. width:fit-content keeps the hover chip hugging the
       label without making this inline, which would drag the page's own strut
       into the line box. */
    display: block;
    width: fit-content;
    text-align: left;
    cursor: pointer;
    transition: color 0.15s, background 0.15s;
}
.media-addline:hover { color: var(--diary-accent); background: #faf7ef; }
.media-addline .mal-ic { font-size: 0.95rem; margin-right: 7px; }

/* Writing invitations and add lines — the page's own handwriting */
.addline {
    font-family: var(--font-hand);
    font-weight: 500;
    font-size: 1.14rem;
    color: #a89e88;
    border: 1px dashed #d8d0ba;
    border-radius: 8px;
    padding: 10px 16px;
    text-align: center;
    cursor: pointer;
    background: none;
    width: 100%;
    display: block;
    transition: all 0.15s;
}
.addline:hover { color: var(--diary-accent); border-color: var(--diary-accent); background: #faf7ef; }
.addline-sm { font-size: 1.04rem; padding: 8px 14px; }

.page-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 26px; padding-top: 16px; border-top: 1px solid #ece5d4; }
.page-action {
    font-family: var(--font);
    font-size: 0.78rem;
    color: var(--ink-soft);
    background: none;
    border: 1px solid #e2dac6;
    border-radius: 100px;
    padding: 6px 13px;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    transition: all 0.15s;
}
.page-action:hover { border-color: var(--diary-accent); color: var(--diary-accent); background: #faf7ef; }

/* Writing area — the editor is the page, not a modal */
.write-box {
    font-family: var(--font-serif);
    font-size: 1.02rem;
    line-height: 30px;
    color: var(--ink);
    width: 100%;
    min-height: 130px;
    background: rgba(255,255,255,0.55);
    border: 1px solid #ddd4bd;
    border-radius: var(--radius-sm);
    padding: 10px 12px;
    resize: vertical;
}
.write-box:focus { border-color: var(--diary-accent); box-shadow: 0 0 0 3px rgba(138,111,78,0.10); }
.write-actions { display: flex; gap: 10px; margin-top: 10px; align-items: center; justify-content: flex-end; }
.write-hint { font-size: 0.72rem; color: var(--ink-soft); font-style: italic; }

/* ─── The paper button family ───
   Every button that sits on the diary page or in one of its dialogs. Platform
   blue belongs to the chrome above the page and must never land on the paper —
   reach for these instead of .btn-primary / .btn-danger inside the diary.
   The gradients are shallow on purpose: they read as ink density on a pressed
   card, not as a gel button. */
.btn-paper, .btn-paper-strong, .btn-paper-danger, .btn-paper-quiet {
    font-family: var(--font);
    font-size: 0.8rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    border: 1px solid transparent;
    border-radius: 100px;
    padding: 8px 20px;
    cursor: pointer;
    transition: border-color 0.15s, box-shadow 0.15s, background 0.15s, color 0.15s, transform 0.1s;
}
.btn-paper:active, .btn-paper-strong:active,
.btn-paper-danger:active, .btn-paper-quiet:active { transform: translateY(1px); }
.btn-paper:focus-visible, .btn-paper-strong:focus-visible,
.btn-paper-danger:focus-visible, .btn-paper-quiet:focus-visible {
    outline: 2px solid var(--diary-accent);
    outline-offset: 2px;
}

/* Ivory — the everyday commit, quiet enough to sit inside the writing */
.btn-paper {
    color: var(--diary-accent);
    background: linear-gradient(180deg, #fdfaf1, var(--diary-accent-soft));
    border-color: #ded0b4;
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.75), 0 1px 2px rgba(90,70,40,0.10);
}
.btn-paper:hover {
    border-color: var(--diary-accent);
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.75), 0 2px 7px rgba(90,70,40,0.15);
}
.btn-paper:active { box-shadow: inset 0 1px 3px rgba(90,70,40,0.16); }

/* Sepia — the primary action of a dialog */
.btn-paper-strong {
    color: #fdfaf1;
    background: linear-gradient(180deg, #9b7d59, var(--diary-accent));
    border-color: #7a6144;
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.2), 0 1px 3px rgba(90,70,40,0.22);
}
.btn-paper-strong:hover {
    background: linear-gradient(180deg, #a68a63, #93764f);
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.2), 0 3px 9px rgba(90,70,40,0.26);
}

/* Oxblood — deleting and clearing */
.btn-paper-danger {
    color: #fdf6f3;
    background: linear-gradient(180deg, #ad4a3b, var(--diary-danger));
    border-color: #833024;
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.18), 0 1px 3px rgba(90,40,30,0.22);
}
.btn-paper-danger:hover {
    background: linear-gradient(180deg, #b95445, #a13f31);
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.18), 0 3px 9px rgba(90,40,30,0.26);
}
.btn-paper-danger:focus-visible { outline-color: var(--diary-danger); }

/* Outline — cancel, and anything that walks away */
.btn-paper-quiet {
    color: var(--ink-soft);
    background: none;
    border-color: #e0d8c4;
}
.btn-paper-quiet:hover { color: var(--diary-accent); border-color: var(--diary-accent); background: #faf7ef; }

.page-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-top: 10px;
    padding: 0 4px;
}
.page-nav {
    background: none;
    border: none;
    font-family: var(--font-serif);
    font-style: italic;
    font-size: 0.95rem;
    color: var(--ink-soft);
    cursor: pointer;
    padding: 6px 8px;
    border-radius: 6px;
}
.page-nav:hover:not(:disabled) { color: var(--diary-accent); background: rgba(255,255,255,0.6); }
.page-nav:disabled { opacity: 0.3; cursor: default; }
.page-count { font-size: 0.75rem; color: var(--ink-soft); }

/* Corner hit-zones — bottom-left back, bottom-right forward.
   Direction maps to time; reversed reads instantly wrong. */
.turn { position: absolute; bottom: 0; width: 66px; height: 66px; cursor: pointer; border: none; background: none; padding: 0; z-index: 2; }
.turn.next { right: 0; }
.turn.prev { left: 0; }
.turn .fold {
    position: absolute; bottom: 0; right: 0;
    width: 0; height: 0;
    border-left: 66px solid transparent;
    border-bottom: 66px solid rgba(0,0,0,0.05);
    transition: border-bottom-color 0.18s;
}
.turn.prev .fold {
    left: 0; right: auto;
    border-left: none;
    border-right: 66px solid transparent;
    border-bottom: 66px solid rgba(0,0,0,0.05);
}
.turn:hover .fold { border-bottom-color: rgba(0,0,0,0.13); }
.turn .arrow {
    position: absolute; bottom: 10px;
    color: var(--ink-soft);
    font-family: var(--font-hand);
    font-size: 1.1rem;
}
.turn.next .arrow { right: 12px; }
.turn.prev .arrow { left: 12px; }
.turn[disabled] { display: none; }

/* ═══════════════════════════════════════════
   MEDIA ON THE PAGE
═══════════════════════════════════════════ */
.album { margin: 4px 0 14px; }
/* Written under the photo, the way a caption is written on a print. The half-
   degree tilt is what stops it reading as a form field. It carries every
   caption in the album joined by a middot, so it is capped to the widest album
   layout — left to run the full page width it stops reading as belonging to
   the pictures above it. */
.album-cap {
    font-family: var(--font-hand);
    font-size: 1.06rem;
    font-weight: 500;
    color: var(--ink-soft);
    max-width: 436px;
    margin-top: 8px;
    line-height: 1.35;
    transform: rotate(-0.5deg);
    transform-origin: left center;
}

.mount {
    background: var(--color-white);
    padding: 6px;
    border: 1px solid #eae4d4;
    box-shadow: 0 1px 2px rgba(0,0,0,.06), 0 4px 12px rgba(60,50,30,.10);
    position: relative;
    cursor: pointer;
    display: block;
    width: 100%;
    font-family: inherit;
    text-align: left;
}
.mount:hover { box-shadow: 0 1px 2px rgba(0,0,0,.08), 0 8px 20px rgba(60,50,30,.16); }
.mount:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }

/* Reserve the box: thumbnail dimensions are unknown until load, and an
   unreserved box reflows the page as pictures land. */
.ph {
    width: 100%;
    display: block;
    background: #efe9dc;
    position: relative;
    overflow: hidden;
    aspect-ratio: 1 / 1;
}
.ph img { width: 100%; height: 100%; object-fit: cover; display: block; }

.album-one { width: 268px; max-width: 100%; padding: 9px; transform: rotate(-1.1deg); }
.album-one .ph { aspect-ratio: 4 / 3; }

/* ── Vertical media (TikTok, Reels, Shorts) ──
   Applied only when EVERY item in the album is vertical — see renderAlbum().
   A 9/16 print, and a NARROWER one. Keeping the landscape width and only
   changing the ratio is what makes a vertical clip 440px tall on a lone tile
   and 740px as a hero — taller than the phone it was shot on, and the opposite
   of "the cap is what keeps the writing dominant". Narrowing the mount gives a
   tall small frame, which is how a vertical print is stuck into a scrapbook. */
.mount.tall .ph { aspect-ratio: 9 / 16; }
.album-one.tall { width: 190px; }
.album-hero.tall { max-width: 220px; }

.album-strip { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; max-width: 430px; }
.album-strip .mount:nth-child(1) { transform: rotate(-1.3deg); }
.album-strip .mount:nth-child(2) { transform: rotate(0.6deg); }
.album-strip .mount:nth-child(3) { transform: rotate(-0.4deg); }

.album-hero { padding: 9px; max-width: 436px; transform: rotate(-0.7deg); }
.album-hero .ph { aspect-ratio: 16 / 10; }
.album-row { display: flex; gap: 9px; margin-top: 11px; max-width: 436px; padding-left: 10px; flex-wrap: wrap; }
.album-row .mount { padding: 5px; width: 88px; }
.album-row .mount:nth-child(2) { transform: rotate(0.9deg); }
.album-row .mount:nth-child(3) { transform: rotate(-0.7deg); }
.album-more {
    width: 88px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--diary-accent-soft);
    border: 1px dashed #cdc4ad;
    color: var(--ink-soft);
    font-family: var(--font-hand);
    font-weight: 600;
    font-size: 1.14rem;
    padding: 5px;
    cursor: pointer;
}
.album-more:hover { border-color: var(--diary-accent); color: var(--diary-accent); }

.play {
    position: absolute; top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    width: 34px; height: 34px;
    border-radius: 50%;
    background: rgba(255,255,255,0.94);
    display: flex; align-items: center; justify-content: center;
    z-index: 2;
    box-shadow: 0 2px 8px rgba(0,0,0,0.25);
}
.play::before {
    content: "";
    border-left: 10px solid #333;
    border-top: 7px solid transparent;
    border-bottom: 7px solid transparent;
    margin-left: 3px;
}
.play.neutral::before { border-left-color: #8a8a8a; }

.badge-host {
    position: absolute; left: 5px; bottom: 5px;
    z-index: 2;
    background: rgba(255,255,255,0.93);
    border-radius: 3px;
    padding: 1px 5px;
    font-size: 0.6rem;
    font-weight: 600;
    color: #555;
    letter-spacing: 0.02em;
}

/* A dead link should read as a photo removed from a scrapbook, never as a
   browser error icon. Link rot is guaranteed; this is a designed state. */
.ph-gone, .ph-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    text-align: center;
    padding: 8px;
}
.ph-gone {
    background: #f5f1e6;
    border: 1px dashed #cdc4ad;
    color: #a89e88;
}
.ph-gone span, .ph-card span {
    font-family: var(--font-hand);
    font-weight: 500;
    font-size: 0.98rem;
    line-height: 1.2;
}
.ph-card { background: linear-gradient(150deg, #efe9dc, #ded5c2); color: #7a7060; }
.ph-card .ic { font-size: 1.2rem; font-style: normal; }
.ph-card.ig { background: linear-gradient(150deg, #f3e3ea, #e6cfe0); color: #8a6a80; }
.ph-card.tt { background: linear-gradient(150deg, #dfeff0, #c8dfe2); color: #4e7076; }
.ph-card.vid { background: linear-gradient(150deg, #e2e6ee, #c9d1de); color: #5b6577; }

/* ═══════════════════════════════════════════
   LIGHTBOX
═══════════════════════════════════════════ */
.lightbox {
    position: fixed;
    inset: 0;
    z-index: 1300;
    background: rgba(20,18,14,0.92);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 56px 16px 72px;
}
.lb-stage {
    max-width: min(1000px, 100%);
    max-height: 100%;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
}
.lb-stage img, .lb-stage video {
    max-width: 100%;
    max-height: calc(100vh - 150px);
    object-fit: contain;
    display: block;
    border-radius: 3px;
    background: #000;
}
.lb-stage iframe {
    width: 100%;
    max-width: 900px;
    border: none;
    border-radius: 3px;
    background: #000;
    max-height: calc(100vh - 150px);
}
.lb-stage iframe.portrait { max-width: 360px; }
.lb-fallback { text-align: center; color: #e8e3d8; max-width: 460px; }
.lb-fallback p { margin-bottom: 14px; font-size: 0.95rem; line-height: 1.6; }
.lb-fallback .btn { background: #fff; color: #2b2b2b; border-color: #fff; }

.lb-close, .lb-nav {
    position: absolute;
    background: rgba(255,255,255,0.12);
    border: none;
    color: #fff;
    cursor: pointer;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.15s;
}
.lb-close { top: 14px; right: 14px; width: 44px; height: 44px; font-size: 1.6rem; line-height: 1; }
.lb-nav { top: 50%; transform: translateY(-50%); width: 48px; height: 48px; font-size: 2rem; line-height: 1; }
.lb-prev { left: 12px; }
.lb-next { right: 12px; }
.lb-close:hover, .lb-nav:hover { background: rgba(255,255,255,0.26); }
.lb-nav[disabled] { opacity: 0.25; cursor: default; }

.lb-bar {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    padding: 14px 20px calc(14px + env(safe-area-inset-bottom));
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    color: #e8e3d8;
    background: linear-gradient(to top, rgba(0,0,0,0.55), transparent);
}
.lb-caption { font-family: var(--font-hand); font-weight: 500; font-size: 1.1rem; }
.lb-count { font-size: 0.78rem; opacity: 0.75; flex-shrink: 0; }

/* ═══════════════════════════════════════════
   MANAGE MEDIA
═══════════════════════════════════════════ */
.mm-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; margin-bottom: 18px; flex-wrap: wrap; }
.mm-head h2 { font-family: var(--font-serif); font-size: 1.35rem; color: var(--ink); }
.mm-sub { font-size: 0.82rem; color: var(--ink-soft); margin-top: 2px; }

/* Media quota strip. `maxMedia` is the one media cap refused locally, so it is
   the one worth drawing — the user can see the ceiling coming instead of
   meeting it as a toast. `mediaPerNode` is only refused at save and gets the
   warning line below the bar, not a bar of its own: it has no single number to
   fill, being a worst-case across every day. */
.mm-quota { margin: -8px 0 18px; }
.mm-quota-bar {
    height: 8px;
    border-radius: 999px;
    background: var(--paper-edge);
    overflow: hidden;
    box-shadow: inset 0 1px 2px rgba(60, 50, 30, .10);
}
.mm-quota-fill {
    display: block;
    height: 100%;
    width: 0;
    border-radius: 999px;
    background: var(--diary-accent);
    transition: width .25s ease, background-color .25s ease;
}
.mm-quota.is-near .mm-quota-fill { background: #b9822f; }
.mm-quota.is-full .mm-quota-fill { background: var(--diary-danger); }
.mm-quota-note { font-size: 0.8rem; color: var(--ink-soft); margin-top: 6px; }
.mm-quota.is-full .mm-quota-note { color: var(--diary-danger); }
.mm-quota-warn {
    font-size: 0.8rem;
    color: var(--diary-danger);
    background: var(--diary-danger-soft);
    border-radius: var(--radius-sm);
    padding: 6px 10px;
    margin-top: 8px;
}
@media (prefers-reduced-motion: reduce) { .mm-quota-fill { transition: none; } }

.mm-paste-card { margin-bottom: 16px; }
.mm-paste-card h3 { font-size: 0.95rem; color: var(--ink); margin-bottom: 4px; }
.mm-hint { font-size: 0.78rem; color: var(--color-text-light); margin-bottom: 10px; }
.mm-paste-row { display: flex; gap: 10px; align-items: flex-end; margin-top: 10px; flex-wrap: wrap; }
.mm-target-label { display: block; font-size: 0.78rem; font-weight: 600; color: var(--color-text-medium); margin-bottom: 4px; }
.mm-paste-row select { flex: 1; min-width: 180px; }
.mm-paste-left { margin-top: 10px; font-size: 0.8rem; color: #92400e; background: #fffbeb; border: 1px solid #fde68a; border-radius: var(--radius-sm); padding: 8px 11px; }

.mm-toolbar { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; flex-wrap: wrap; }
.mm-progress { font-size: 0.8rem; color: var(--ink-soft); }

.mm-group { margin-bottom: 22px; }
.mm-group-head {
    display: flex; align-items: baseline; gap: 8px;
    font-size: 0.72rem;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--ink-soft);
    border-bottom: 1px solid var(--paper-edge);
    padding-bottom: 6px;
    margin-bottom: 12px;
}
.mm-group-head .n { font-size: 0.7rem; opacity: 0.7; margin-left: auto; letter-spacing: 0; text-transform: none; }
.mm-group.unassigned .mm-group-head { color: #92400e; border-bottom-color: #fde68a; }

.mm-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(178px, 1fr)); gap: 14px; }

.mm-tile { background: var(--color-white); border: 1px solid var(--paper-edge); border-radius: var(--radius-md); padding: 8px; box-shadow: var(--shadow-sm); }
.mm-tile .ph { border-radius: var(--radius-sm); }
/* Reorder arrows — only rendered for attached groups holding two or more.
   Touch targets are 32px; the grid is reached from a phone as often as a desk. */
.mm-order { display: flex; align-items: center; justify-content: center; gap: 6px; margin-top: 7px; }
.mm-arrow {
    width: 32px; height: 32px;
    display: flex; align-items: center; justify-content: center;
    background: none;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    font-size: 0.9rem;
    line-height: 1;
    color: var(--color-text-medium);
    cursor: pointer;
    font-family: inherit;
}
.mm-arrow:hover:not(:disabled) { border-color: var(--color-accent); color: var(--color-accent); }
.mm-arrow:disabled { opacity: 0.35; cursor: default; }
.mm-order-pos {
    font-size: 0.72rem;
    color: var(--color-text-light);
    font-variant-numeric: tabular-nums;
    min-width: 34px;
    text-align: center;
}

.mm-tile-cap {
    font-family: var(--font-hand);
    font-weight: 500;
    font-size: 0.98rem;
    color: var(--ink-soft);
    margin-top: 7px;
    line-height: 1.35;
    word-break: break-word;
}
.mm-tile-cap.none { opacity: 0.55; }
.mm-tile-host { font-size: 0.68rem; color: var(--color-text-light); margin-top: 3px; word-break: break-all; }
.mm-tile-err { font-size: 0.72rem; color: #b3261e; margin-top: 5px; line-height: 1.4; }
.mm-tile-row { display: flex; gap: 6px; margin-top: 9px; flex-wrap: wrap; }
.mm-tile-row select { height: 32px; font-size: 0.78rem; flex: 1; min-width: 110px; }
.mm-mini {
    background: none;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-sm);
    font-size: 0.72rem;
    color: var(--color-text-medium);
    padding: 5px 9px;
    cursor: pointer;
    font-family: inherit;
}
.mm-mini:hover { border-color: var(--color-accent); color: var(--color-accent); }
.mm-mini.danger:hover { border-color: var(--color-error); color: var(--color-error); }

/* ═══════════════════════════════════════════
   MODALS
═══════════════════════════════════════════ */
.modal {
    position: fixed;
    inset: 0;
    z-index: 1100;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
}
.modal.hidden { display: none; }
.modal-overlay { position: absolute; inset: 0; background: rgba(0,0,0,0.45); }

.modal-content {
    position: relative;
    background: var(--color-white);
    border-radius: var(--radius-xl);
    padding: 1.5rem;
    width: 100%;
    max-width: 480px;
    box-shadow: var(--shadow-lg);
    max-height: calc(100vh - 2rem);
    overflow-y: auto;
}
.modal-content-sm { max-width: 380px; }
.modal-content-lg { max-width: 760px; }

.modal-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 0.75rem; gap: 10px; }
.modal-header h3 { font-size: 1.1rem; font-weight: 700; color: var(--color-text-dark); }
.modal-close {
    background: none; border: none;
    font-size: 1.5rem; line-height: 1;
    cursor: pointer;
    color: var(--color-text-light);
    padding: 0 4px;
    font-family: inherit;
    transition: color 0.15s;
}
.modal-close:hover { color: var(--color-text-dark); }
.modal-lede { font-size: 0.84rem; color: var(--color-text-medium); margin-bottom: 1rem; line-height: 1.5; }
/* A note attached to one choice in the dialog above it, not to the dialog —
   hence the accent rule rather than a second block of lede-grey text. */
.modal-note {
    font-size: 0.8rem;
    color: var(--color-text-medium);
    line-height: 1.5;
    margin: -0.35rem 0 0.9rem;
    padding-left: 10px;
    border-left: 2px solid var(--diary-accent);
}
.modal-actions { display: flex; gap: 8px; margin-top: 1.25rem; flex-wrap: wrap; }
.confirm-msg { font-size: 0.95rem; color: var(--color-text-dark); line-height: 1.5; }
.confirm-msg a { color: var(--color-accent); }

/* ─── The diary's own dialogs ───
   Rename and confirm are the page reaching out, not the platform interrupting
   it, so they are dressed as paper: warm scrim, paper card, serif heading, and
   the paper button family. The larger functional modals (media, manage media,
   blog export) stay on platform chrome — they are tool surfaces, not the page
   asking a question. */
#modal-prompt .modal-overlay,
#modal-confirm .modal-overlay { background: rgba(58, 46, 30, 0.42); }

#modal-prompt .modal-content,
#modal-confirm .modal-content {
    background: var(--paper);
    border: 1px solid var(--paper-edge);
    box-shadow: var(--paper-shadow), 0 18px 44px rgba(60,50,30,0.22);
}

/* Serif on the question, sans on everything else. The heading is where the
   dialog earns its place on the desk; a form set in serif throughout starts
   fighting the writing behind it. */
#modal-prompt .modal-header h3,
#modal-confirm .modal-header h3 {
    font-family: var(--font-serif);
    font-size: 1.2rem;
    color: var(--ink);
}
#modal-prompt .modal-close,
#modal-confirm .modal-close { color: var(--ink-soft); }
#modal-prompt .modal-close:hover,
#modal-confirm .modal-close:hover { color: var(--diary-accent); }

#modal-confirm .confirm-msg { color: var(--ink); }
#modal-prompt .form-group label { color: var(--ink-soft); }
#modal-prompt .form-input,
#modal-prompt .form-select {
    font-family: var(--font-serif);
    color: var(--ink);
    background: rgba(255,255,255,0.6);
    border-color: #ddd4bd;
}
#modal-prompt .form-input:focus,
#modal-prompt .form-select:focus {
    border-color: var(--diary-accent);
    box-shadow: 0 0 0 3px rgba(138,111,78,0.10);
}

.media-hosts { font-size: 0.72rem; color: var(--color-text-light); margin-top: 6px; line-height: 1.5; }

.media-preview-row { display: flex; gap: 14px; margin-bottom: 1rem; align-items: flex-start; }
.media-preview {
    width: 132px;
    flex-shrink: 0;
    aspect-ratio: 4 / 3;
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    background: #f2efe8;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    position: relative;
}
.media-preview img { width: 100%; height: 100%; object-fit: cover; }
.mp-placeholder { font-size: 0.76rem; color: var(--color-text-light); text-align: center; padding: 8px; }
.media-preview-info { flex: 1; min-width: 0; }
.mp-status { font-size: 0.85rem; font-weight: 600; }
.mp-status.ok { color: #1a7f4b; }
.mp-status.fail { color: #b3261e; }
.mp-status.pending { color: #9a6b00; }
.mp-status.neutral { color: var(--color-text-medium); }
.mp-note { font-size: 0.78rem; color: var(--color-text-medium); margin-top: 5px; line-height: 1.5; }

.blog-controls { display: grid; grid-template-columns: 2fr 1fr; gap: 12px; margin-bottom: 12px; }
.blog-output {
    width: 100%;
    height: 300px;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.78rem;
    line-height: 1.55;
    background: #fbfaf6;
    resize: vertical;
}

.changelog-modal-content { max-width: 640px; }
.changelog-body { font-size: 0.9rem; line-height: 1.6; }

/* ═══════════════════════════════════════════
   TOAST
═══════════════════════════════════════════ */
.toast-container {
    position: fixed;
    bottom: 32px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 2000;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    pointer-events: none;
    padding: 0 12px;
}
.toast {
    background: var(--color-text-dark);
    color: var(--color-white);
    padding: 0.55rem 1.25rem;
    border-radius: 100px;
    font-size: 0.875rem;
    font-weight: 500;
    box-shadow: var(--shadow-md);
    opacity: 0;
    transform: translateY(8px);
    transition: opacity 0.25s, transform 0.25s;
    max-width: 90vw;
    text-align: center;
}
.toast-visible { opacity: 1; transform: translateY(0); }
.toast-error { background: var(--color-error); }
.toast-success { background: #15803d; }

/* ═══════════════════════════════════════════
   FOOTER
═══════════════════════════════════════════ */
.related-tools { margin-bottom: 10px; line-height: 1.3; }
.related-tools-label {
    color: var(--color-text-light);
    font-weight: 400;
    text-transform: uppercase;
    letter-spacing: 0.09em;
    font-size: 0.7rem;
    margin-right: 12px;
    vertical-align: middle;
}
.related-tools .footer-link { color: var(--color-text-medium); font-weight: 400; font-size: 0.85rem; vertical-align: middle; margin-right: 12px; }
.related-tools .footer-link:hover { color: var(--color-accent); }

.app-footer {
    position: relative;
    max-width: 1200px;
    margin: 2rem auto 0;
    padding: 1.1rem 1.5rem 0.9rem;
    border-top: 1px solid var(--paper-edge);
    text-align: center;
    font-size: 0.8rem;
    color: var(--color-text-light);
    line-height: 1.6;
}
.app-footer p { margin: 0; }
.app-footer p:first-of-type {
    font-family: var(--font-serif);
    font-style: italic;
    font-size: 0.85rem;
    color: var(--color-text-medium);
}
.app-footer p + p { margin-top: 4px; }
.app-footer p .footer-link { color: var(--color-accent); }
.app-footer p .footer-link:hover { color: var(--color-accent-hover); text-decoration: underline; }
.footer-link { color: var(--color-text-medium); text-decoration: none; transition: color 0.15s; }
.footer-link:hover { color: var(--color-accent); }
.footer-separator { margin: 0 6px; color: var(--color-border); }
.version-badge {
    background: none; border: none;
    font-size: 0.8rem;
    color: var(--color-text-light);
    cursor: pointer;
    font-family: var(--font);
    padding: 0;
    transition: color 0.15s;
}
.version-badge:hover { color: var(--color-accent); }

/* ═══════════════════════════════════════════
   SEO ABOUT SECTION
═══════════════════════════════════════════ */
.about-section { max-width: 1200px; margin: 26px auto 0; }

.about-toggle {
    width: 100%;
    background: transparent;
    border: none;
    border-top: 1px dotted var(--paper-edge);
    padding: 9px 1.5rem;
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 6px;
    transition: color 0.2s;
    font-size: 0.8rem;
    font-weight: 500;
    color: #94a3b8;
    text-align: left;
    font-family: inherit;
    justify-content: center;
}
.about-toggle[aria-expanded="true"] { justify-content: flex-start; }
.about-toggle:not([aria-expanded="true"]) .about-title { flex: 0 1 auto; }
.about-toggle:hover { color: #64748b; }
.about-toggle[aria-expanded="true"] .toggle-icon { transform: rotate(180deg); }

.about-icon { font-size: 0.8rem; flex-shrink: 0; }
.about-title { flex: 1; }
.toggle-icon { font-size: 0.65rem; transition: transform 0.3s ease; flex-shrink: 0; }

.about-content {
    background: #ffffff;
    border: 1px solid var(--paper-edge);
    border-radius: 8px;
    padding: 28px 24px;
    margin-top: 4px;
    animation: aboutSlideDown 0.3s ease;
}
@keyframes aboutSlideDown {
    from { opacity: 0; transform: translateY(-8px); }
    to   { opacity: 1; transform: translateY(0); }
}

.about-content h2 {
    color: #1a2332;
    font-size: 1.25rem;
    margin-bottom: 20px;
    line-height: 1.4;
    border-bottom: 2px solid var(--color-accent);
    padding-bottom: 10px;
}
.about-content h3 { color: #1a2332; font-size: 1rem; margin-top: 20px; margin-bottom: 12px; font-weight: 600; }
.about-content p { margin-bottom: 10px; color: #4b5563; line-height: 1.65; font-size: 0.9rem; }
.about-content code { background: #f1f3f5; padding: 1px 5px; border-radius: 3px; font-size: 0.85em; }

.about-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 28px; margin-bottom: 24px; }
.about-column ul, .about-column ol { margin: 12px 0; padding-left: 22px; }
.about-column li { margin-bottom: 8px; line-height: 1.6; color: #1f2937; font-size: 0.9rem; }
.about-column li strong { color: #1a2332; }

.how-to-steps { counter-reset: step-counter; list-style: none; padding-left: 0; }
.how-to-steps li { counter-increment: step-counter; margin-bottom: 18px; padding-left: 44px; position: relative; }
.how-to-steps li::before {
    content: counter(step-counter);
    position: absolute;
    left: 0; top: 0;
    background: var(--color-accent);
    color: white;
    width: 30px; height: 30px;
    border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    font-weight: bold; font-size: 0.9rem;
}
.how-to-steps li strong { display: block; margin-bottom: 4px; color: #1a2332; }
.how-to-steps li p { margin: 0; line-height: 1.6; color: #6b7280; }

.features-section { background: #f8f7f3; padding: 20px; border-radius: 10px; margin-top: 20px; }
.features-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 16px; margin-top: 12px; }
.feature-item { background: white; padding: 14px; border-radius: 8px; border-left: 3px solid var(--color-accent); }
.feature-item strong { display: block; color: #1a2332; margin-bottom: 5px; font-size: 0.9rem; }
.feature-item p { margin: 0; font-size: 0.85rem; line-height: 1.5; color: #6b7280; }

.use-cases-section { margin-top: 20px; }
.use-cases-section ul { margin-top: 12px; padding-left: 22px; }
.use-cases-section li { margin-bottom: 8px; line-height: 1.6; font-size: 0.9rem; }
.use-cases-section li strong { color: #1a2332; }

.keywords-section { margin-top: 18px; color: #9aa3ad; }

/* ═══════════════════════════════════════════
   RESPONSIVE
═══════════════════════════════════════════ */
@media (max-width: 1000px) {
    .diary-shell { grid-template-columns: 1fr; }
    .toc-open-btn { display: flex; }

    /* Two panes at phone width is a drawer, not a split view — and it is a
       drawer you create in, so it keeps every add and rename affordance. */
    .toc {
        position: fixed;
        top: 0; left: 0; bottom: 0;
        width: min(320px, 88vw);
        z-index: 1250;
        border-radius: 0;
        border: none;
        border-right: 1px solid var(--paper-edge);
        padding: 8px 8px 12px;
        transform: translateX(-102%);
        transition: transform 0.24s ease;
        display: flex;
        flex-direction: column;
        box-shadow: 0 0 40px rgba(0,0,0,0.22);
    }
    .toc.open { transform: translateX(0); }
    .toc-scroll { max-height: none; flex: 1; }
    .toc-close {
        display: flex;
        position: absolute;
        top: 6px; right: 4px;
        width: 34px; height: 34px;
        align-items: center; justify-content: center;
        background: none; border: none;
        font-size: 1.5rem; line-height: 1;
        color: var(--ink-soft);
        cursor: pointer;
    }
    .toc-head { padding-right: 40px; }
    .rowact { opacity: 1; }
    .act-actions { opacity: 1; }
    /* Nothing here can be dragged — HTML5 drag does not fire from a touchscreen.
       A grip that does nothing is worse than no grip; the ⋮ menu does the work. */
    .toc-grip { display: none; }

    .toc-backdrop {
        position: fixed; inset: 0;
        background: rgba(0,0,0,0.42);
        z-index: 1240;
    }

    .page { max-height: none; }
}

@media (max-width: 900px) {
    /* The hero's two columns do not stack — the art floats and the copy wraps
       around it, so a narrow screen only has to make the picture smaller. This
       is allergy-diary's `.welcome-art` move and it is here for the same reason:
       stacked, a 440px illustration is a slab wedged between the headline and a
       block of controls, and it pushes the form a full screen down.
       flow-root drops the grid and contains the float; .hero-words clears it so
       no input ever slides underneath. */
    .setup-hero { display: flow-root; padding: 22px 20px 20px; }
    .hero-art { float: right; width: 168px; max-width: 40%; margin: 0 0 10px 18px; }
    .setup-head { margin-bottom: 0; }
    .hero-words { clear: both; }
    .hero-words > :first-child { margin-top: 22px; }   /* the desktop reset would butt it against the art */
    .setup-kicker { font-size: 1.6rem; }
    .setup-lede { font-size: 1rem; margin-top: 12px; }
    .signpost { font-size: 1.45rem; margin-top: 14px; }
    .setup-have { padding: 22px 20px 22px; }
}

@media (max-width: 860px) {
    .about-grid { grid-template-columns: 1fr; gap: 16px; }
    .blog-controls { grid-template-columns: 1fr; }
}

@media (max-width: 600px) {
    .hero-art { width: 132px; margin-left: 14px; }
    .have-grid { grid-template-columns: minmax(0, 1fr); gap: 14px; }
    .have-head { margin-bottom: 12px; }
    /* Two date fields side by side is where the entry screen overflows: a date
       input has a wide min-content, and `1fr` columns do not shrink past it. */
    .date-input-group { grid-template-columns: minmax(0, 1fr); }
    /* Same reasoning for the date-mode pills: two full sentences will not sit
       on one 375px line, so they take a row each rather than shrinking. */
    #setup-section .radio-group { flex-wrap: wrap; gap: 10px; }
    #setup-section .radio-group > label { flex: 1 1 100%; }
}

@media (max-width: 768px) {
    .logo-image { height: 34px; }
    .tool-name-btn { font-size: 1.25rem; }
    .page { padding: 28px 20px 60px 38px; --margin-x: 22px; }
    .album-strip { max-width: 100%; }
    .about-content { padding: 20px 16px; }
    .features-grid { grid-template-columns: 1fr; }
    .about-toggle { font-size: 0.8rem; padding: 9px 2px; }
}

@media (max-width: 480px) {
    .header-inner { padding: 0.5rem 1rem; }
    .logo-image { height: 30px; }
    .header-icon-btn, .menu-btn { width: 36px; height: 36px; }
    .container { padding: 12px 1rem 24px; }
    .card { padding: 16px; }
    .setup-hero { padding: 18px 16px 16px; }
    .setup-have { padding: 18px 16px 18px; }
    .setup-kicker { font-size: 1.35rem; }
    .setup-lede { font-size: 0.95rem; }
    .signpost { font-size: 1.3rem; }
    .hero-art { width: 116px; margin-left: 12px; }
    .have-card { padding: 16px 17px 18px; }
    #create-btn { font-size: 0.95rem; padding: 13px 20px; }
    .modal-content { padding: 1.15rem; border-radius: var(--radius-lg); }
    .date-line { font-size: 1.3rem; }
    /* The rules stay a 32px repeat at every width — .page only changes its
       padding on mobile — so the line height must not drop to 30 here either. */
    .prose { font-size: 1rem; line-height: 32px; }
    /* A landscape print takes the full column on a phone; a vertical one must
       not, or 9/16 of the content width is nearly the whole screen. */
    .album-one { width: 100%; }
    .album-one.tall { width: 172px; }
    .mm-grid { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); }
    .media-preview-row { flex-direction: column; }
    .media-preview { width: 100%; }
    .turn { width: 54px; height: 54px; }
    .turn .fold { border-left-width: 54px; border-bottom-width: 54px; }
    .turn.prev .fold { border-right-width: 54px; border-left-width: 0; }
}

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