/* ===== Custom DaisyUI Theme ===== */
[data-theme="shipmate"] {
    --b1: 100% 0 0;            /* base-100: white */
    --b2: 97% 0.002 250;       /* base-200 */
    --b3: 93% 0.004 250;       /* base-300 */
    --bc: 25% 0.07 250;        /* base-content: navy-ish */
    --p: 30% 0.12 250;         /* primary: navy */
    --pf: 25% 0.14 250;        /* primary-focus */
    --pc: 100% 0 0;            /* primary-content: white */
    --s: 51% 0.19 90;          /* secondary: gold */
    --sf: 46% 0.17 90;         /* secondary-focus */
    --sc: 25% 0.07 250;        /* secondary-content: navy */
    --a: 44% 0.13 250;         /* accent: blue */
    --af: 38% 0.14 250;
    --ac: 100% 0 0;
    --n: 25% 0.07 250;         /* neutral */
    --nf: 20% 0.08 250;
    --nc: 100% 0 0;
    --rounded-btn: 0.5rem;
    --rounded-badge: 1rem;
    --rounded-box: 0.75rem;
}

/* ===== Base styles ===== */
html {
    scroll-behavior: smooth;
}

/*  ------------------------------------------ the footer ends the page

    Derrick, 2026-09-09, from an iPad: "on ipad these scroll way past the
    footer. we need to ensure the footer is the bottom of the page on EVERY
    PAGE. that is a ui bug."

    Two separate causes, both of them iOS, and both fixed here rather than on
    the pages — the layouts already lay this out correctly (body is a flex
    column, main is flex:1, the footer is the last child), so nothing about an
    individual page is wrong and a per-page fix would be fourteen fixes.

    1. min-h-screen is Tailwind's `min-height: 100vh`, and on iOS `100vh` is the
       LARGE viewport — the height the page would have if the address bar were
       hidden. With the bar showing, the document is taller than what you can
       see, so every page has a strip of scroll below the footer whether or not
       it has enough content to need one. `100dvh` is the height actually on
       screen right now, which is the number this wants. 100vh stays first as
       the fallback for anything that does not know dvh.

    2. Rubber banding. Past the end of the document Safari keeps scrolling and
       paints the canvas background — the light page ground — so the footer
       lifts off the bottom of the screen and a slab of grey appears under it.
       overscroll-behavior-y stops the page from doing that.

    body.min-h-screen, not body: the utility is injected by the Tailwind play
    CDN at runtime, which puts its stylesheet AFTER this one. The extra class
    is what wins the cascade against it. */
body.min-h-screen {
    min-height: 100vh;
    min-height: 100dvh;
}

html,
body {
    overscroll-behavior-y: none;
}

/* ===== GSAP animation helpers ===== */
.gsap-fade-up {
    opacity: 0;
    transform: translateY(40px);
}
.gsap-fade-in {
    opacity: 0;
}
.gsap-scale-in {
    opacity: 0;
    transform: scale(0.95);
}

/* ===== Image zoom on hover ===== */
.img-zoom {
    overflow: hidden;
}
.img-zoom img {
    transition: transform 0.7s ease-out;
}
.img-zoom:hover img {
    transform: scale(1.1);
}

/* ===== Mobile menu hamburger animation =====
   translate must come BEFORE rotate so the offset is in screen space, not the
   rotated coordinate frame (otherwise both lines shift diagonally left and the
   right side of the X gets cut off). */
.menu-open .hamburger-line:nth-child(1) {
    transform: translateY(8px) rotate(45deg);
}
.menu-open .hamburger-line:nth-child(2) {
    opacity: 0;
    transform: scaleX(0);
}
.menu-open .hamburger-line:nth-child(3) {
    transform: translateY(-8px) rotate(-45deg);
}

/* ===== Scrollbar hide for filter bar ===== */
.scrollbar-hide {
    -ms-overflow-style: none;
    scrollbar-width: none;
}
.scrollbar-hide::-webkit-scrollbar {
    display: none;
}

/* ===== Line clamp utilities ===== */
.line-clamp-1 {
    display: -webkit-box;
    -webkit-line-clamp: 1;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.line-clamp-2 {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* ===== DaisyUI card overrides to match original ===== */
.card-compact .card-body {
    padding: 1rem 1.5rem;
}

/* Override DaisyUI defaults that conflict */
.btn {
    text-transform: none;
}

/* ===== Submission Guidelines (rendered from TinyMCE HTML) ===== */
.guidelines-content { font-size: 0.875rem; color: #6b7280; line-height: 1.6; }
.guidelines-content h3 { font-family: 'Oswald', system-ui, sans-serif; font-size: 1rem; font-weight: 600; color: #062160; margin-bottom: 1rem; }
.guidelines-content h4 { font-size: 0.875rem; font-weight: 600; color: #062160; margin-bottom: 0.25rem; margin-top: 0; }
.guidelines-content h5 { font-size: 0.8rem; font-weight: 600; color: #062160; margin-bottom: 0.25rem; }
.guidelines-content p { margin-bottom: 0.75rem; }
.guidelines-content hr { border: none; border-top: 1px solid #e5e7eb; margin: 0.75rem 0; }
.guidelines-content a { color: #1E5DAB; text-decoration: none; }
.guidelines-content a:hover { text-decoration: underline; }
.guidelines-content table { width: 100%; font-size: 0.8rem; margin-bottom: 0.5rem; }
.guidelines-content table td { padding: 0.15rem 0.5rem 0.15rem 0; }
.guidelines-content table td:last-child { font-weight: 500; color: #062160; }
.guidelines-content ul, .guidelines-content ol { padding-left: 1.25rem; margin-bottom: 0.75rem; }
.guidelines-content li { margin-bottom: 0.25rem; }
.guidelines-content strong { color: #062160; }

/* ===== Form banner (shipmate-alert) =====
   A refined callout used at the top of the submission forms. Soft tinted
   background, left accent bar, muted typography that sits alongside the form
   card rather than shouting over it. */
.shipmate-alert {
    display: flex;
    align-items: flex-start;
    gap: 0.85rem;
    padding: 0.9rem 1.15rem;
    border-radius: 0.6rem;
    border: 1px solid var(--alert-border, #dbeafe);
    border-left-width: 4px;
    border-left-color: var(--alert-accent, #1E5DAB);
    background: var(--alert-bg, #f1f7ff);
    color: #1f2937;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03);
}
.shipmate-alert__icon {
    flex-shrink: 0;
    width: 1.25rem;
    height: 1.25rem;
    color: var(--alert-accent, #1E5DAB);
    margin-top: 2px;
}
.shipmate-alert__body {
    flex: 1;
    font-size: 0.9rem;
    line-height: 1.55;
    color: #374151;
}
.shipmate-alert__body > *:first-child { margin-top: 0; }
.shipmate-alert__body > *:last-child { margin-bottom: 0; }
.shipmate-alert__body p { margin: 0 0 0.4rem; }
.shipmate-alert__body strong { color: var(--alert-accent, #1E5DAB); font-weight: 600; }
.shipmate-alert__body a {
    color: var(--alert-accent, #1E5DAB);
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 2px;
    font-weight: 600;
}
.shipmate-alert__body a:hover { text-decoration-thickness: 2px; }

.shipmate-alert--info     { --alert-accent: #1E5DAB; --alert-bg: #f1f7ff; --alert-border: #c9dcf7; }
.shipmate-alert--success  { --alert-accent: #0f766e; --alert-bg: #eefaf5; --alert-border: #b7e4cf; }
.shipmate-alert--warning  { --alert-accent: #b45309; --alert-bg: #fff8e7; --alert-border: #fadfa0; }
.shipmate-alert--error    { --alert-accent: #b91c1c; --alert-bg: #fff0f0; --alert-border: #f5c6c6; }

/* ===== TinyMCE fullscreen escape hatch =====
   `position: fixed` gets anchored to the nearest ancestor with a transform/filter,
   not the viewport, so any parent that Tailwind/GSAP has transformed will clip the
   fullscreen editor. When the fullscreen class is active we flatten ancestor
   transforms, lift overflow, and pin the editor container to the actual viewport. */
html.tox-fullscreen,
html.tox-fullscreen body {
    overflow: hidden !important;
}
html.tox-fullscreen .container,
html.tox-fullscreen .card,
html.tox-fullscreen .card-body,
html.tox-fullscreen aside,
html.tox-fullscreen .submit-form,
html.tox-fullscreen .scribe-form,
html.tox-fullscreen .scribe-sidebar,
html.tox-fullscreen .obit-form,
html.tox-fullscreen fieldset,
html.tox-fullscreen #form-fields,
html.tox-fullscreen #form-fields > * {
    transform: none !important;
    filter: none !important;
    perspective: none !important;
    overflow: visible !important;
}
.tox.tox-tinymce.tox-fullscreen {
    position: fixed !important;
    inset: 2.5rem !important;
    width: auto !important;
    height: auto !important;
    z-index: 2147483000 !important;
    border-radius: 0.5rem !important;
    box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.35) !important;
}
html.tox-fullscreen body::before {
    content: "";
    position: fixed;
    inset: 0;
    background: rgba(6, 33, 96, 0.45);
    z-index: 2147482999;
    pointer-events: none;
}

/* ===== Submission loading overlay =====
   Shown when the user clicks Submit and validation passes. Blocks the entire
   viewport, signals progress, and reassures the user that the wait is normal.
   Toggled from the form submit handler in Submit.cshtml. */
.submit-overlay {
    position: fixed; inset: 0;
    display: flex; align-items: center; justify-content: center;
    padding: 1.25rem;
    background:
        radial-gradient(circle at 30% 0%, rgba(30,93,171,0.55) 0%, transparent 55%),
        linear-gradient(135deg, rgba(4,21,72,0.96) 0%, rgba(6,33,96,0.96) 50%, rgba(10,50,128,0.96) 100%);
    backdrop-filter: blur(4px);
    z-index: 2147482000;
    animation: submit-overlay-in 0.2s ease both;
}
@keyframes submit-overlay-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}
.submit-overlay__card {
    background: #fff;
    border-radius: 16px;
    padding: 2rem 2.25rem 1.85rem;
    width: 100%; max-width: 420px;
    text-align: center;
    box-shadow: 0 30px 60px -15px rgba(0,0,0,0.45), 0 0 0 1px rgba(255,255,255,0.06);
    animation: submit-overlay-card 0.4s cubic-bezier(.2,.8,.2,1) both;
}
@keyframes submit-overlay-card {
    from { opacity: 0; transform: translateY(12px) scale(0.98); }
    to   { opacity: 1; transform: none; }
}
.submit-overlay__logo {
    height: 36px; width: auto; margin: 0 auto 1.25rem; display: block;
}
.submit-overlay__spinner {
    width: 56px; height: 56px;
    margin: 0 auto 1rem;
    animation: submit-overlay-spin 1.1s linear infinite;
}
.submit-overlay__spinner svg { width: 100%; height: 100%; display: block; }
@keyframes submit-overlay-spin {
    to { transform: rotate(360deg); }
}
.submit-overlay__title {
    font-family: 'Oswald', system-ui, sans-serif;
    font-size: 1.25rem; font-weight: 600; color: #062160;
    margin: 0 0 0.4rem;
}
.submit-overlay__sub {
    font-size: 0.875rem; color: #4b5563; margin: 0 0 0.6rem; line-height: 1.5;
}
.submit-overlay__hint {
    font-size: 0.7rem; color: #9ca3af; margin: 0;
    letter-spacing: 0.02em; text-transform: uppercase; font-weight: 500;
}

/* ===== SOP link (used in the Submit-page guidelines sidebar) ===== */
.sop-link {
    display: flex; align-items: center; gap: 0.5rem;
    padding: 0.65rem 0.85rem;
    background: #eef5ff;
    border: 1px solid #c9dcf7;
    border-radius: 8px;
    color: #062160;
    font-size: 0.825rem;
    text-decoration: none;
    transition: background-color 0.15s ease, border-color 0.15s ease;
}
.sop-link:hover { background: #dceaff; border-color: #1E5DAB; }
.sop-link strong { color: #062160; font-weight: 600; }
.sop-link span { flex: 1; }
.sop-link__chev { color: #1E5DAB; }

/* ===== SOP page (markdown render + edit) =====
   Renders the markdown returned from /api/sop/{page}. Styling matches the
   rest of the magazine — Inter body, Oswald headings, navy/blue accents. */
.sop-doc {
    background: #fff;
    border-radius: 12px;
    box-shadow: 0 8px 24px -8px rgba(6, 33, 96, 0.15);
    padding: 2rem 2.25rem;
    color: #1f2937;
    font-size: 0.95rem;
    line-height: 1.7;
}
@media (max-width: 640px) {
    .sop-doc { padding: 1.25rem 1.25rem; font-size: 0.9rem; }
}
.sop-doc h1, .sop-doc h2, .sop-doc h3, .sop-doc h4, .sop-doc h5 {
    font-family: 'Oswald', system-ui, sans-serif;
    color: #062160;
    font-weight: 600;
    line-height: 1.25;
}
.sop-doc h1 {
    font-size: 1.85rem;
    border-bottom: 3px solid #1E5DAB;
    padding-bottom: 0.6rem;
    margin: 0 0 1rem;
}
.sop-doc h2 {
    font-size: 1.4rem;
    margin: 2.25rem 0 0.75rem;
    padding-bottom: 0.4rem;
    border-bottom: 1px solid #e5e7eb;
}
.sop-doc h3 {
    font-size: 1.15rem;
    margin: 1.75rem 0 0.5rem;
    color: #0A3280;
}
.sop-doc h4 {
    font-size: 0.95rem;
    margin: 1.25rem 0 0.4rem;
    color: #374151;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.sop-doc p { margin: 0 0 1rem; }
.sop-doc strong { color: #062160; font-weight: 600; }
.sop-doc em { color: #374151; }
.sop-doc a {
    color: #1E5DAB; text-decoration: underline;
    text-underline-offset: 2px; text-decoration-thickness: 1px;
    font-weight: 500;
}
.sop-doc a:hover { color: #062160; text-decoration-thickness: 2px; }
.sop-doc ul, .sop-doc ol { margin: 0 0 1rem; padding-left: 1.5rem; }
.sop-doc li { margin-bottom: 0.35rem; }
.sop-doc li > p { margin-bottom: 0.35rem; }
.sop-doc hr {
    border: none; border-top: 1px solid #e5e7eb;
    margin: 2.25rem 0;
}
.sop-doc blockquote {
    border-left: 4px solid #FFD700;
    background: #fffbe6;
    padding: 0.85rem 1.1rem;
    margin: 1.25rem 0;
    border-radius: 0 8px 8px 0;
    color: #4b3a00;
    font-size: 0.9rem;
}
.sop-doc blockquote p { margin: 0 0 0.4rem; }
.sop-doc blockquote p:last-child { margin: 0; }
.sop-doc blockquote strong { color: #b45309; }
.sop-doc code {
    background: #eef5ff;
    color: #062160;
    padding: 0.1rem 0.4rem;
    border-radius: 4px;
    font-family: 'SF Mono', Consolas, Menlo, monospace;
    font-size: 0.85em;
}
.sop-doc pre {
    background: #062160; color: #e0ecff;
    padding: 1rem 1.15rem;
    border-radius: 8px;
    overflow-x: auto;
    font-size: 0.85rem;
    margin: 1.25rem 0;
}
.sop-doc pre code { background: transparent; padding: 0; color: inherit; }

.sop-doc table {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    margin: 1.25rem 0;
    font-size: 0.875rem;
    border: 1px solid #e5e7eb;
    border-radius: 8px;
    overflow: hidden;
    background: #fff;
}
.sop-doc table thead th {
    background: #062160; color: #fff;
    text-align: left;
    font-family: 'Oswald', system-ui, sans-serif;
    font-weight: 500;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    font-size: 0.75rem;
    padding: 0.7rem 0.95rem;
}
.sop-doc table th, .sop-doc table td {
    padding: 0.65rem 0.95rem;
    border-bottom: 1px solid #f1f5f9;
    vertical-align: top;
}
.sop-doc table tr:last-child td { border-bottom: none; }
.sop-doc table tbody tr:nth-child(even) td { background: #fafbfc; }
.sop-doc table tbody tr:hover td { background: #eef5ff; }

.sop-loading {
    display: inline-flex; align-items: center; gap: 0.5rem;
    color: #6b7280; font-size: 0.9rem;
}
.sop-empty { text-align: center; padding: 2.5rem 1rem; color: #6b7280; }
.sop-empty h2 { color: #062160; margin: 0 0 0.5rem; font-family: 'Oswald', sans-serif; }

/* Toolbar buttons (header + editor toolbar share styles) */
.sop-btn {
    display: inline-flex; align-items: center; gap: 0.4rem;
    padding: 0.45rem 0.9rem;
    border-radius: 8px; border: 1px solid transparent; cursor: pointer;
    font-family: inherit; font-size: 0.82rem; font-weight: 600;
    transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease, transform 0.05s ease;
}
.sop-btn:active { transform: translateY(1px); }
.sop-btn:disabled { opacity: 0.6; cursor: not-allowed; }
.sop-btn-ghost {
    background: rgba(255,255,255,0.08);
    border-color: rgba(255,255,255,0.18);
    color: #fff;
}
.sop-btn-ghost:hover { background: rgba(255,255,255,0.15); }
.sop-btn-gold {
    background: #FFD700; color: #062160;
    border-color: #C5A600;
}
.sop-btn-gold:hover { background: #ffe04a; }
.sop-btn-navy {
    background: #062160; color: #fff;
    border-color: #062160;
}
.sop-btn-navy:hover { background: #1E5DAB; border-color: #1E5DAB; }

/* Edit toolbar */
.sop-edit-toolbar {
    display: flex; align-items: center; gap: 0.5rem;
    padding: 0.65rem 0.85rem;
    background: #f8fafc;
    border: 1px solid #e5e7eb;
    border-radius: 10px 10px 0 0;
    border-bottom: 0;
}
.sop-edit-toolbar .sop-btn-ghost {
    background: #fff; color: #4b5563; border-color: #d1d5db;
}
.sop-edit-toolbar .sop-btn-ghost:hover { background: #f3f4f6; color: #062160; }
.sop-status {
    margin-left: auto;
    font-size: 0.8rem; color: #6b7280;
}
.sop-status--ok { color: #047857; font-weight: 500; }
.sop-status--error { color: #b91c1c; font-weight: 500; }
.sop-edit-hint {
    font-size: 0.75rem; color: #9ca3af;
    margin: 0.5rem 0 0;
}

/* EasyMDE container override to match the toolbar */
.EasyMDEContainer {
    border: 1px solid #e5e7eb !important;
    border-radius: 0 0 10px 10px !important;
    background: #fff;
}
.EasyMDEContainer .CodeMirror {
    border: 0 !important;
    border-radius: 0 !important;
    font-family: 'SF Mono', Consolas, Menlo, monospace;
    font-size: 0.9rem;
    min-height: 520px;
}
.editor-toolbar {
    border: 0 !important; border-bottom: 1px solid #e5e7eb !important;
    background: #fafbfc !important;
}
.editor-toolbar button { color: #4b5563 !important; border-radius: 6px !important; }
.editor-toolbar button:hover, .editor-toolbar button.active {
    background: #eef5ff !important; border-color: #c9dcf7 !important;
}

@media print {
    header, footer, #view-as-dock, .sop-header button, #sop-editor-shell { display: none !important; }
    section.relative { padding: 0 !important; }
    section.relative .absolute { display: none !important; }
    .sop-header { color: #062160 !important; }
    .sop-header h1, .sop-header p { color: #062160 !important; }
    .sop-doc { box-shadow: none; border: 1px solid #e5e7eb; }
}

/* ===== Word count badge =====
   Pill-style indicator that sits below the story editor. Default styling
   uses the navy/blue palette; flips to amber when within 10% of the limit
   and red when over. Color is driven by classes so callers can stay out of
   inline styles. */
.word-count-badge {
    display: inline-flex;
    align-items: center;
    padding: 0.4rem 0.85rem;
    font-size: 0.875rem;
    font-weight: 600;
    line-height: 1.2;
    border-radius: 9999px;
    background: #eef5ff;
    color: #062160;
    border: 1px solid #c9dcf7;
    letter-spacing: 0.01em;
    transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.word-count-badge.is-warning {
    background: #fff8e7;
    color: #92400e;
    border-color: #fadfa0;
}
.word-count-badge.is-error {
    background: #fff0f0;
    color: #b91c1c;
    border-color: #f5c6c6;
}
.word-count-details {
    font-size: 0.8rem;
    color: #4b5563;
    font-weight: 500;
}
.word-count-details.is-error { color: #b91c1c; }

/* ===== Attachments dropzone =====
   Drag-and-drop card used on the submit/obituary forms. Hidden <input type="file">
   sits inside; the visible UI is driven by attachments.js. */
.attachments-dropzone {
    position: relative;
    border: 2px dashed #cbd5e1;
    border-radius: 0.75rem;
    background: #fafbfc;
    padding: 1rem;
    transition: border-color 0.15s ease, background-color 0.15s ease;
}
.attachments-dropzone.is-dragover {
    border-color: #1E5DAB;
    background: #eef5ff;
}
.attachments-dropzone .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;
}
.attachments-prompt {
    text-align: center;
    padding: 1.5rem 0.75rem;
    cursor: pointer;
    border-radius: 0.5rem;
    transition: background-color 0.15s ease;
}
.attachments-prompt:hover { background: rgba(30, 93, 171, 0.04); }
.attachments-prompt__icon {
    width: 2.5rem; height: 2.5rem;
    margin: 0 auto 0.5rem;
    color: #1E5DAB;
    opacity: 0.7;
}
.attachments-prompt__title {
    font-size: 0.95rem; font-weight: 600;
    color: #062160; margin: 0 0 0.15rem;
}
.attachments-prompt__sub { font-size: 0.8rem; color: #6b7280; margin: 0; }
.attachments-prompt__hint { font-size: 0.7rem; color: #9ca3af; margin: 0.4rem 0 0; }
.attachments-browse-link {
    color: #1E5DAB; font-weight: 600;
    background: none; border: 0; padding: 0; cursor: pointer;
    text-decoration: underline; text-underline-offset: 2px;
}
.attachments-browse-link:hover { color: #062160; }
.attachments-prompt--compact { padding: 0.5rem 0.75rem; }
.attachments-prompt--compact .attachments-prompt__icon { width: 1.5rem; height: 1.5rem; margin-bottom: 0.25rem; }
.attachments-prompt--compact .attachments-prompt__title { font-size: 0.8rem; font-weight: 500; color: #6b7280; }
.attachments-prompt--compact .attachments-prompt__sub { font-size: 0.75rem; }
.attachments-prompt--compact .attachments-prompt__hint { display: none; }

.attachments-list {
    list-style: none; padding: 0; margin: 0 0 0.75rem;
    display: flex; flex-direction: column; gap: 0.5rem;
}
.attachment-item {
    display: grid;
    grid-template-columns: 36px 1fr auto;
    gap: 0.75rem;
    align-items: center;
    padding: 0.6rem 0.75rem;
    background: #ffffff;
    border: 1px solid #e5e7eb;
    border-radius: 0.5rem;
    transition: border-color 0.15s ease, background-color 0.15s ease;
}
.attachment-item--error {
    border-color: #fca5a5;
    background: #fff7f7;
}
.attachment-icon {
    display: flex; align-items: center; justify-content: center;
    width: 36px; height: 36px;
    border-radius: 0.4rem;
    background: #eef5ff;
    color: #1E5DAB;
}
.attachment-item--error .attachment-icon { background: #fef2f2; color: #b91c1c; }
.attachment-body { min-width: 0; }
.attachment-title {
    display: flex; align-items: baseline; gap: 0.5rem;
    font-size: 0.875rem; font-weight: 500; color: #1f2937;
    min-width: 0;
}
.attachment-name {
    flex: 1; min-width: 0;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.attachment-size {
    font-size: 0.7rem; color: #9ca3af; flex-shrink: 0;
}
.attachment-status { display: block; font-size: 0.72rem; margin-top: 0.1rem; }
.attachment-status--muted { color: #6b7280; }
.attachment-status--ok    { color: #047857; }
.attachment-status--error { color: #b91c1c; font-weight: 500; }
.attachment-progress {
    display: block; width: 100%; height: 4px; margin-top: 0.4rem;
    appearance: none; -webkit-appearance: none;
    border: 0; border-radius: 9999px; overflow: hidden;
    background: #e5e7eb;
}
.attachment-progress::-webkit-progress-bar { background: #e5e7eb; border-radius: 9999px; }
.attachment-progress::-webkit-progress-value { background: #1E5DAB; transition: width 0.2s ease; border-radius: 9999px; }
.attachment-progress::-moz-progress-bar { background: #1E5DAB; border-radius: 9999px; }
.attachment-remove {
    background: none; border: 0; cursor: pointer;
    padding: 0.4rem; border-radius: 0.4rem;
    color: #9ca3af;
    display: flex; align-items: center; justify-content: center;
    transition: color 0.15s ease, background-color 0.15s ease;
}
.attachment-remove:hover { color: #b91c1c; background: #fef2f2; }
.attachment-remove:focus-visible { outline: 2px solid #1E5DAB; outline-offset: 2px; }

@media (max-width: 480px) {
    .attachment-item {
        grid-template-columns: 32px 1fr auto;
        gap: 0.5rem;
        padding: 0.55rem 0.6rem;
    }
    .attachment-icon { width: 32px; height: 32px; }
    .attachment-title { flex-wrap: wrap; }
    .attachment-size { font-size: 0.65rem; }
}

/* ===== GSAP fallback: ensure elements are visible if animation doesn't fire ===== */
@keyframes ensure-visible { to { opacity: 1; } }
.page-header, .info-card, .form-card, .login-header, .login-card,
.submit-header, .submit-form, .success-content, .article-image,
.scribe-header, .scribe-sidebar, .scribe-form,
.memorial-header, .memorial-card, .memorial-hero, .memorial-paragraph, .memorial-image, .memorial-body,
.issues-header, .issue-featured, .issues-archive, .issue-card,
.sop-header, .sop-content {
    animation: ensure-visible 0s 1.5s forwards;
}

/* Skip link — first thing in the tab order, invisible until focused.
   Lives in site.css because _SiteHeader is shared by every layout. */
.site-skiplink {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 100;
    background: #FFD700;
    color: #062160;
    font: 600 13px 'Inter', system-ui, sans-serif;
    padding: .6rem 1rem;
    text-decoration: none;
    border-radius: 0 0 6px 0;
}

.site-skiplink:focus {
    left: 0;
}

/* ===== Obituary form — destination choice =====
   The two cards on /submit-obituary. LAYOUT is done in Tailwind utilities on the element itself,
   not here: Tailwind comes from the CDN and is always current, while this file can be a cached
   copy, and a card whose flex row has not arrived collapses into a radio stacked above its own
   label. What is left here is only the selected/hover tint, which degrades to nothing. */
.obit-choice { transition: border-color .15s ease, background-color .15s ease, box-shadow .15s ease; }
.obit-choice:hover { border-color: #c7cdd6; background: #fcfcfd; }
.obit-choice:has(input:checked) {
  border-color: #062160;
  background: rgba(6, 33, 96, 0.04);
  box-shadow: inset 0 0 0 1px #062160;
}
.obit-choice:has(input:focus-visible) { outline: 2px solid rgba(6, 33, 96, .4); outline-offset: 2px; }
.obit-choice em { font-style: italic; }

/* ===== Obituary proof — the draft a family reads before it runs =====
   Set the way it will actually be published, because the point of showing it is that they can see
   what will appear. The print variant carries the house style: Times New Roman, italics, and ship
   names in small caps with the USS dropped — "if that's not there, you lose the visual that
   indicates it's a ship". */
.obit-proof { font-size: 1rem; line-height: 1.7; color: #1a1a1a; }
.obit-proof p { margin: 0 0 1rem 0; }
.obit-proof p:last-child { margin-bottom: 0; }
.obit-proof--print {
  font-family: 'Times New Roman', Times, serif;
  font-size: 1.05rem;
  border: 1px solid #e5e7eb;
  border-left: 3px solid #062160;
  background: #fcfcfd;
  padding: 1.25rem 1.5rem;
}
.obit-proof .obit-smallcaps,
.obit-proof--print .obit-smallcaps {
  font-variant-caps: small-caps;
  font-variant: small-caps;
  letter-spacing: .02em;
}

/*  The obituary form with its sidebar scoped away.

    The sidebar holds the Last Call house rules, which only apply to a print submission, so on the
    website branch it is hidden. The grid it left behind is still five columns wide with the form
    pinned to three of them — so without this the form renders hard against a 500px hole where the
    sidebar used to be, which reads as a broken page rather than a shorter one.

    It takes the full grid back and re-centres at a readable measure. Not stretched: a form field
    the width of a 2560px monitor is worse than the hole was. */
@media (min-width: 1024px) {
  .obit-layout--solo > .obit-form {
    grid-column: 1 / -1;
    max-width: 54rem;
    width: 100%;
    /*  justify-self, not margin-inline:auto. A grid item defaults to justify-self:stretch, and a
        max-width that stops it stretching leaves it packed at the start of the track rather than
        centred — which just moves the empty column from the left to the right. */
    justify-self: center;
  }
}

/*  The obituary chooser — the step before the form.

    Timothy and Luke replaced the in-form destination toggle with this on 2026-08-21: the choice
    governs half the questions, so it belongs before them rather than as the first of them. Cards
    rather than radios because these are two different errands, not two settings. */
.obit-path { text-decoration: none; color: inherit; }
.obit-path-kicker {
  font-family: 'Oswald', system-ui, sans-serif;
  font-size: .68rem;
  letter-spacing: .18em;
  text-transform: uppercase;
  /*  Was #8a8f98, which is 3.25:1 on white and fails WCAG 1.4.3 at this size.
      These two kickers - "Most people start here" and "Just letting us know" -
      are the labels that tell a family which of the two paths to take, on the
      form whose address is being printed in the magazine. Uppercase at .68rem
      with .18em tracking is already hard work to read; faint as well is worse.
      #5c6169 clears 4.5:1 and keeps the same cool grey. */
  color: #5c6169;
}
.obit-path-go {
  display: inline-block;
  margin-top: 1rem;
  font-family: 'Oswald', system-ui, sans-serif;
  font-size: .78rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: #062160;
}
.obit-path:hover .obit-path-go { color: #1E5DAB; }

/*  Where they are, once they have chosen. A statement with a way back, not a control — the value
    is re-derived server-side on every post, so this cannot be argued with from the page. */
.obit-chosen {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: .85rem 1.1rem;
  background: #f4f6f9;
  border: 1px solid #e3e6ea;
  border-radius: .5rem;
}
.obit-chosen-kicker {
  font-family: 'Oswald', system-ui, sans-serif;
  font-size: .62rem;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: #8a8f98;
}
.obit-chosen-title { font-weight: 600; color: #062160; }
/*  "Change" — the way back out of a chosen path. Measured 48x20 on a phone, under WCAG 2.2
    SC 2.5.8's 24px minimum, and it is the control somebody reaches for when they realise they
    picked the wrong form. Padded to 24px rather than set larger: it should stay quieter than the
    destination it sits beside. The negative inline-end margin keeps the text on the same optical
    edge it had before the padding. */
.obit-chosen-change {
  margin-left: auto;
  margin-right: -.4rem;
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  min-height: 24px;
  padding: .25rem .4rem;
  font-size: .82rem;
  color: #1E5DAB;
  text-decoration: underline;
}

/*  "Also post on the website". Sits under the destination because it is the one place the two
    destinations still meet. */
.obit-also {
  display: flex;
  align-items: flex-start;
  gap: .75rem;
  margin-top: .9rem;
  padding: .85rem 1.1rem;
  border: 1px solid #e3e6ea;
  border-radius: .5rem;
  cursor: pointer;
}
.obit-also:hover { border-color: #062160; }
.obit-also-title { display: block; font-weight: 600; color: #062160; }
.obit-also-note {
  display: block;
  font-size: .84rem;
  color: #6b7280;
  line-height: 1.45;
  margin-top: .15rem;
}

/*  The obituary form as one column.

    It was a two-column grid with the rules in a sticky sidebar. Scoping the sidebar to the print
    branch left the form pinned beside an empty third of the page, which then needed its own rule to
    reclaim the space — a lot of machinery to make a column vanish tidily. Reading the guidance
    first is simpler and better: the rules that decide what somebody should write belong before the
    box they write it in. */
.obit-single {
  max-width: 52rem;
  margin-inline: auto;
}

/*  Guidance, set as a quiet preface rather than a card competing with the form. The left rule is
    the same navy used for the section headings, so it reads as part of the same document. */
.obit-guide {
  margin-bottom: 2rem;
  padding: 1.35rem 1.5rem;
  background: #f7f9fc;
  border-left: 3px solid #062160;
  border-radius: 0 .5rem .5rem 0;
}
.obit-guide-title {
  font-family: 'Oswald', system-ui, sans-serif;
  font-size: .78rem;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: #062160;
  margin: 0 0 .75rem;
}
/*  The copy is editor-authored HTML from Bridge, so it is styled by tag rather than by class —
    whatever headings and lists they write have to land somewhere sensible. */
.obit-guide-body > *:first-child { margin-top: 0; }
.obit-guide-body > *:last-child  { margin-bottom: 0; }
.obit-guide-body h3 {
  font-family: 'Oswald', system-ui, sans-serif;
  font-size: .95rem;
  font-weight: 600;
  color: #062160;
  margin: 1rem 0 .4rem;
}
.obit-guide-body h3:first-child { margin-top: 0; }

/* ==========================================================================
   The 2026-09-01 client review — shared page furniture

   Four of that meeting's asks are not page-level at all; they are one piece of
   furniture used everywhere, and each was being re-declared per page. They live
   here so there is a single place to change them:

     the bounding box      the one content box every page sits inside
     the page ground       off pure white
     the colophon          one minimal footer, site-wide
     back / title states   one padded back control, one hover colour

   Every colour below is measured against WCAG 2.2 SC 1.4.3 (4.5:1 for body
   text) rather than eyeballed; the ratios are written next to each one.
   ========================================================================== */

/*  ---------------------------------------------------------- bounding box

    Derrick, 2026-09-01: "one thing we're doing is scooting this here, this
    edge, to align with this home here. That's going to be our sort of bounding
    box across the board."

    The main site has always had that box — Tailwind's `.container mx-auto px-4
    lg:px-8`, which is what the header, the footer and every page section use.
    What did not sit on it was anything written outside Tailwind, the Never
    Forgotten section most of all: it built its own box from a clamp() gutter
    and a single 1536px cap, so at a 1400px window the memorial's content
    started at x=40 while the chrome above it started at x=92. Same page, two
    left edges.

    Tailwind's container is not a clamp — it is a max-width that STEPS at each
    breakpoint — so nothing that approximates it with a smooth function can line
    up with it at more than one width. These custom properties restate the real
    steps, so a plain stylesheet can sit on the identical grid by construction.

    --page-content is the box itself: min(available, the step) less the same
    padding the container applies. Applied with margin-inline:auto rather than
    padding, so the element's own box IS the content box — anything positioned
    against it (the memorial's back link is absolute) still lands on the edge. */
:root {
    --page-max: 100%;
    --page-pad: 1rem; /* Tailwind px-4 */
    --page-content: min(100% - var(--page-pad) * 2, calc(var(--page-max) - var(--page-pad) * 2));
}

@media (min-width: 640px) {
    :root {
        --page-max: 640px;
    }
}

@media (min-width: 768px) {
    :root {
        --page-max: 768px;
    }
}

@media (min-width: 1024px) {
    :root {
        --page-max: 1024px;
        --page-pad: 2rem; /* Tailwind lg:px-8 */
    }
}

@media (min-width: 1280px) {
    :root {
        --page-max: 1280px;
    }
}

@media (min-width: 1536px) {
    :root {
        --page-max: 1536px;
    }
}

/*  Anything outside Tailwind that wants the site's bounding box asks for it
    here rather than re-deriving it. */
.site-page {
    width: var(--page-content);
    margin-inline: auto;
}

/*  --------------------------------------------------------- the page ground

    Alex, 2026-09-01: "that white kind of hurts my eyes a little... maybe they
    get a little bit more gray than bright white."

    #F2F3F5 rather than the existing usna.gray #F5F5F5, which is barely off
    white; this is a step further and still reads as paper rather than as a
    panel. Cards keep `bg-white`, so the grey is the ground BETWEEN them, which
    is what gives the page its separation.

    Measured against everything that sits directly on it:
      #062160 navy body text      13.57:1   (AA and AAA)
      #4b5563 gray-600             6.80:1
      #626b7a (see below)          4.85:1

    The one casualty was Tailwind's gray-500 #6b7280. It clears 4.5:1 on pure
    white by a hair — 4.86:1 — and nothing else, so ANY move off white fails it:
    it needs a ground of at least L=0.9215 (about #F6F6F6) to hold AA, and that
    is not a grey anyone would notice. Rather than pick an invisible grey,
    gray-500 is darkened one notch instead. It is a single rule, it applies
    everywhere the class is used, and it is darker — so it also improves the
    white cards it appears on, where it was 4.86:1 and is now 5.38:1. */
:root {
    --page-ground: #F2F3F5;
}

/*  On <body>, replacing the `bg-white` both layouts carried. A class rather
    than a Tailwind arbitrary value so the token stays the single source. */
.site-ground {
    background-color: var(--page-ground);
}

/*  Beats the Tailwind Play CDN's own `.text-gray-500` on specificity rather
    than on document order: the CDN injects its stylesheet into <head> at
    runtime, so it lands after this file and would win a tie. */
body .text-gray-500 {
    color: #626b7a;
}

/*  ------------------------------------------------------------- the colophon

    Derrick, 2026-09-01: "I made this new footer here to match the Never
    Forgotten... that will be consistent across everything." Luke: "should
    change the footer across the entire [site]."

    So the memorial's minimal charcoal row is now the site's only footer, and
    the navy block with the logo, the tagline, the link row and the divider is
    gone. The links it carried — Articles, Contribute, Issues, In Memoriam —
    are every one of them in the header nav under the same permissions, so
    nothing became unreachable by losing them here.

    Derrick also asked for the thumbnail to go: "I think we can even remove that
    small thumbnail." That was the 28px shipmate-logo-white.png, and it is what
    made the old footer read as chrome rather than as a colophon.

    One layout at every width. The old footer had a responsive variant and so
    arrived as a 256px centred stack on a phone and a 188px spread row on a
    desktop — the same element reading as two different objects. This is small
    enough at any width that it never needs to become something else.

    Colours are the memorial's own tokens, restated here because this sheet
    loads on pages that never see never-forgotten.css. On #1b1e24:
      #a6a294 copy    6.53:1
      #948f83 links   5.18:1
      #c9a24b hover   6.96:1  */
:root {
    --colophon-ground: #1b1e24;
    --colophon-ink: #a6a294;
    --colophon-link: #948f83;
    --colophon-link-hover: #c9a24b;
}

.site-colophon {
    flex: 0 0 auto;
    display: flex;
    flex-wrap: wrap;
    gap: 0 1.5rem;
    justify-content: center;
    padding: .55rem clamp(1rem, 4vw, 2.5rem);
    background: var(--colophon-ground);
    font: 400 12px/1.6 'Inter', system-ui, -apple-system, sans-serif;
    letter-spacing: .04em;
    color: var(--colophon-ink);
}

/*  WCAG 2.2 SC 2.5.8 wants a 24x24 target. At 12px these links measured 17px
    tall in the geometry audit, so the BOX is padded up to the minimum rather
    than the type being enlarged — the type size is fine, the hit area was not.
    Vertical padding only, so the row keeps its height and reads as before.

    Dropping the thumbnail made this more important, not less: what is left is
    text-only links with nothing tall beside them to set the row height. */
.site-colophon > span,
.site-colophon a {
    display: inline-flex;
    align-items: center;
    min-height: 24px;
    padding-block: .45rem;
}

.site-colophon a {
    color: var(--colophon-link);
    text-decoration: none;
    transition: color .2s ease;
}

    .site-colophon a:hover,
    .site-colophon a:focus-visible {
        color: var(--colophon-link-hover);
    }

/*  --------------------------------------------------------- the home hero

    Luke, 2026-09-01: "can we also shorten the hero image so that way... I just
    want to make sure that they see there's content underneath of it."
    Derrick's answer is the spec: "We can adjust this based on viewport
    height... right now I believe it's based on pixels. We can make it so that
    it forces to be say, viewport height is like the percentage of this. So this
    is like 55, 60 percent."

    It was indeed pixels — the hero had no height of its own, so it was however
    tall the logo (h-16/h-24/h-32) plus the copy and the buttons happened to be.
    On a tall monitor that left it short and floating; on a laptop it filled the
    fold. Either way its relationship to the fold was accidental.

    58% of the viewport, with the header's 112px above it, puts the bottom of
    the hero about two-thirds of the way down whatever screen it is on, so there
    is always something visible below it. That is the whole ask.

    dvh, not vh: on a phone vh is the LARGEST viewport — the one with the
    browser chrome retracted — so a vh-sized hero is taller than the space
    actually on screen until you scroll. vh is declared first as the fallback
    for anything that does not know dvh.

    Clamped at both ends. 58dvh on its own collapses to 217px on a landscape
    phone, shorter than the content inside it; the 20rem floor and the 34rem
    ceiling keep it a hero at both extremes. min-height rather than height, so
    the content can always grow past it instead of being clipped. */
.home-hero {
    display: grid;
    align-content: center;
    min-height: clamp(20rem, 58vh, 34rem);
}

@supports (height: 1dvh) {
    .home-hero {
        min-height: clamp(20rem, 58dvh, 34rem);
    }
}

/*  ------------------------------------------------------- the back control

    Luke, 2026-09-01: "We also standardized the spacing of the back button."

    Every back link on the site had its own padding, or none: the article hero's
    was a pill at px-3/py-1, the one at the foot of the article was bare text
    with no box at all, and the memorial's was bare text too. One shape and one
    padding wherever the word "back" appears.

    The padding is also what makes it a real target — bare 13px text is a 17px
    tall hit area, under the 24x24 that SC 2.5.8 asks for.

    Shape and spacing only, deliberately: colour stays with the call site,
    because the same control sits on a photograph in one place and on paper in
    another. A hover background here would win on specificity over the
    `bg-black/20` the article-hero pill sets and wash it out over the image. */
.site-back {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    min-height: 24px;
    padding: .5rem .85rem;
    border-radius: 9999px;
    text-decoration: none;
    transition: color .2s ease, background-color .2s ease;
}

/*  ---------------------------------------------------------- title on hover

    Derrick, 2026-09-01: "when we hover here, make the title gold as well."
    Card and list titles hovered to usna-blue; they go gold now.

    #B8860B is the site's gold and it is already in use — Pages/InMemoriam.cshtml
    sets it on .lastcall-title — but it measures 3.25:1 on white and 2.93:1 on
    the new ground. These titles are 16-18px semibold, which is not "large
    scale" under WCAG 2.2 (that needs 18.66px BOLD, or 24px), so they need the
    full 4.5:1 and #B8860B cannot give it. A hover state is text like any other;
    the success criterion has no exemption for it.

    --shipmate-gold-ink is the same colour two steps down the X11 darkgoldenrod
    ramp that #B8860B itself comes from, so it is that gold rather than a new
    one invented for the occasion:
      #8B6508 on white    5.30:1
      #8B6508 on #F2F3F5  4.77:1
    #B8860B stays as the token for display-size and decorative use, which is
    what it was already doing. */
:root {
    --shipmate-gold: #B8860B;
    --shipmate-gold-ink: #8B6508;
}

.title-gold {
    transition: color .25s ease;
}

.group:hover .title-gold,
.group:focus-visible .title-gold,
.group:focus-within .title-gold {
    color: var(--shipmate-gold-ink);
}

/* ==========================================================================
   The limited-release homepage — Never Forgotten as the banner

   Derrick, 2026-09-03: "the main banner being the never forgotten and the links
   and everything only focusing on the issues and 9/11 stuff."
   And 2026-09-04: "we want a better background and make the colors match keep
   the blue overlay on the hero banner for cohesiveness."

   So the banner is on the SITE's palette, not the memorial's. The first pass
   borrowed never-forgotten.css's charcoal ground and antique gold, which made a
   handsome banner that read as a different site above the fold: navy chrome,
   charcoal hero, navy stats band. The navy scrim is the thing that ties the
   banner to the header above it and the stats band below it, and it is the same
   scrim the chapel hero carried before — so the treatment is unchanged and only
   the photograph and the words inside it are new.

   Everything here is therefore the site's own #062160 navy and #FFD700 gold,
   set with the Tailwind classes the rest of the page uses. What survives from
   the memorial is the SERIF and nothing else: "Never Forgotten" is set in EB
   Garamond, as it is on the memorial's own masthead, because the section's voice
   is the one part of it that should carry onto the homepage.
   ========================================================================== */
/*  The memorial's serif, owned here.

    site.css is the one stylesheet BOTH layouts load, so a token both the
    memorial and the main site need belongs in it — the same reasoning that put
    --shipmate-gold here. never-forgotten.css now reads --nf-serif from this
    rather than declaring the stack a second time; it kept its own name because
    ~90 rules in that sheet and its two companions reference it.

    The face itself is requested per-page: Pages/Index.cshtml for this banner,
    _MemorialLayout for the section. A token is not a font. */
:root {
    --memorial-serif: 'EB Garamond', Georgia, 'Times New Roman', serif;
}

/*  Shorter than the chapel hero it replaced, on purpose.

    Luke's team, 2026-09-09: "Decreasing vertical height of the homepage hero
    image so people see more of Jimmy's letter so they know to scroll down."

    The PADDING is what actually shortens it at a desktop width, and it is worth
    being precise about that: at 1440x900 the banner is taller than its own
    min-height, so the box is sized by what is inside it plus the block padding.
    Trimming 4.5rem to 3rem a side takes 48px off, and 48px is the difference
    between the letter starting below the fold and its kicker, its gold rule and
    its first line of prose all clearing it — which is the ask. An edge of the
    next thing is what tells a reader there is a next thing.

    min-height comes down too — 58vh/34rem to 44vh/26rem — for the case the
    padding cannot reach: a short, wide window, where the floor rather than the
    content decides the height. Both are overrides of .home-hero rather than
    edits to it, because the article heroes on other pages still want the taller
    frame.

    Not lower than 44vh: the emblem, the kicker, a clamped 4.5rem headline, the
    rule, the lede and two buttons still have to sit inside it without crowding,
    and below about 40vh they start to. */
.home-memorial {
    position: relative;
    overflow: hidden;
    /* Shows through only where the photograph has not painted yet. */
    background-color: #062160;
    padding-block: clamp(1.25rem, 3vw, 2.25rem);
    min-height: clamp(17rem, 44vh, 26rem);
}

@supports (height: 1dvh) {
    .home-memorial {
        min-height: clamp(17rem, 44dvh, 26rem);
    }
}

/*  The banner photograph needs no rule of its own: it is pre-cropped to 2.6:1 —
    the hero band's own proportion at the desktop step — so `w-full h-full
    object-cover` in the markup is the whole of it, and centred is where
    object-position already starts. See the banner comment in Pages/Index.cshtml
    for what the crop takes and why. */

/*  The blue overlay, and the reason the banner reads as part of this site.

    #062160 is the site navy, the same one the header bar above and the stats
    band below are painted in, so the photograph sits between two navy bands
    rather than interrupting them.

    Left-to-right, because the words are on the left: .93 where the headline and
    lede sit, easing to .58 at the right edge where the benches are the only
    thing there and are meant to be seen. Measured on the worst pixel under the
    text — lit gravel between two benches — white/72 body copy holds 8.2:1 and
    the white headline 13:1.

    Deeper than the chapel hero's 80/60/35, because the Pentagon frame is shot
    in full sun on pale concrete and gravel. It can afford to be: the benches
    are shape rather than colour, so heavy navy reads as a duotone of the
    photograph and not as a photograph with something thrown over it. */
.home-memorial-scrim {
    position: absolute;
    inset: 0;
    background: linear-gradient(to right,
        rgba(6, 33, 96, .93) 0%,
        rgba(6, 33, 96, .80) 45%,
        rgba(6, 33, 96, .58) 100%);
}

/*  A horizontal gradient only works while the words occupy the left of the
    frame. Below the desktop step they occupy all of it — the lede wraps to the
    right edge — so the scrim flattens to a near-even navy and the picture
    becomes texture rather than a subject beside the type. */
@media (max-width: 1023px) {
    .home-memorial-scrim {
        background: linear-gradient(to right,
            rgba(6, 33, 96, .94) 0%,
            rgba(6, 33, 96, .88) 60%,
            rgba(6, 33, 96, .82) 100%);
    }
}

.home-memorial-emblem {
    height: clamp(38px, 4.2vw, 52px);
    width: auto;
    display: block;
    margin-bottom: clamp(.5rem, 1vw, .85rem);
}

/*  Type follows the memorial masthead's rhythm — see .nf-mast-* in
    never-forgotten.css — one step larger, because this is a banner rather than a
    nameplate over three doors. Colour is the site's: white and white/70 over
    navy, exactly as the chapel hero set it. */
.home-memorial-kicker {
    font: 600 clamp(10px, 1vw, 12px)/1 'Inter', system-ui, sans-serif;
    letter-spacing: .28em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, .75);
}

.home-memorial-title {
    font: 400 clamp(2.5rem, 6.5vw, 4.5rem)/1.02 var(--memorial-serif);
    color: #fff;
    margin: .35rem 0 .1rem;
}

/*  Space above the line, the same change and the same reason as .nf-mast-sub in
    never-forgotten.css: the headline above is the memorial's name and this is the
    fact under it, not its second line. Derrick, 2026-09-08. Slightly larger here
    than on the gateway because this type is a step bigger. */
.home-memorial-sub {
    margin-top: clamp(.6rem, 1.2vw, .95rem);
    font: italic 400 clamp(1rem, 1.7vw, 1.35rem) var(--memorial-serif);
    color: rgba(255, 255, 255, .75);
}

/*  #FFD700 — the site's gold, the same one the stats band and the buttons use.
    It was the memorial's muted #c9a24b; on a navy ground next to a gold button
    the two golds read as a mistake rather than as a palette. */
.home-memorial-rule {
    height: 2px;
    width: 64px;
    margin: .9rem 0 0;
    border: 0;
    border-radius: 1px;
    background: #FFD700;
}

.home-memorial-lede {
    margin-top: .85rem;
    max-width: 34rem;
    font-size: clamp(.95rem, 1.2vw, 1.075rem);
    line-height: 1.65;
    color: rgba(255, 255, 255, .72);
}

/*  ------------------------------------------------------ the three doors

    Faces / Stories / Voices, in the site's card idiom rather than the memorial
    gateway's full-height columns. Each one deep-links into its section, so a
    visitor who knows what they came for does not land back on the chooser.

    Deliberately NOT a copy of .nf-col: no photo bloom, no column swipe, no
    masthead lift. Those belong to the gateway, whose whole job is choosing. This
    is a homepage pointing at it, so it hovers like every other card here.

    The picture zoom is the site's own .img-zoom, carried on the anchor in the
    markup — that is genuine reuse and it is what the deleted .featured-card did.

    The rest stays in CSS on purpose, and two attempts to move it to utilities
    are the reason:

      `aspect-[4/5] rounded-box` — the cards rendered at ZERO HEIGHT. daisyUI is
      a prebuilt stylesheet here rather than a Tailwind plugin (see _Layout), so
      `rounded-box` is not a class Tailwind knows, and the Play CDN emitted no
      rule for the arbitrary aspect-ratio either. A property that decides whether
      the component has a box at all cannot depend on a runtime class scanner.

      `transition-all duration-500` — the cards rendered BLANK, stuck at
      opacity 0 with their ScrollTrigger reporting progress 1. `transition-all`
      transitions *opacity*, and opacity is exactly what the GSAP reveal
      (Anim.staggerCards) animates: GSAP samples the computed value to record the
      `from` tween's end state, samples it mid-transition, and lands on ~0.

    THIS ELEMENT CARRIES NO TRANSITIONED TRANSFORM, for the same reason one step
    further in. Anim.staggerCards tweens `y: 40 -> 0`, which GSAP writes as a
    per-frame `transform`; a `transition: transform` here would chase every one of
    those writes with its own half-second interpolation and leave the reveal
    damped and still settling after the tween ended. Narrowing `all` to
    `transform, box-shadow` fixed the blanking and kept the damping — so the
    hover lift is gone and the affordance is the shadow plus the .img-zoom push
    on the picture, neither of which GSAP touches.

    --rounded-box is read from the daisyUI theme rather than restating 1rem, so
    the doors round like every `card` on the page.  */
.home-door {
    position: relative;
    display: block;
    overflow: hidden;
    aspect-ratio: 4 / 5;
    border-radius: var(--rounded-box, .75rem);
    background: #062160;
    text-decoration: none;
    box-shadow: 0 4px 6px -1px rgba(0, 0, 0, .1), 0 2px 4px -2px rgba(0, 0, 0, .1);
    transition: box-shadow .4s ease;
}

    .home-door:hover,
    .home-door:focus-visible {
        box-shadow: 0 20px 25px -5px rgba(6, 33, 96, .22), 0 8px 10px -6px rgba(6, 33, 96, .15);
    }

    /*  Grayscale — Derrick, 2026-09-04: "make the three cards under the banner
        faces stories and voices grayscale."

        It is also what makes the row read as one thing. The three doors are
        handed whatever imagery each section has: Faces draws an archival
        portrait that is already monochrome, Stories is a bright blue-sky frame
        of One World Trade, and Voices is a colour still off a video. Side by
        side they were three different photographs; desaturated under the same
        navy scrim they are three panels of the same set.

        The navy scrim sits on a sibling element rather than on the picture, so
        it is unaffected — grayscale under navy is what gives these cards the
        banner's duotone instead of a flat grey. */
    .home-door img {
        width: 100%;
        height: 100%;
        object-fit: cover;
        object-position: 50% 30%;
        filter: grayscale(1);
    }

/*  The same navy the banner scrim uses, so the cards belong to the band above
    them. Opaque at the foot rather than a wash over the whole picture: the words
    need a ground that holds 4.5:1 no matter which of the fourteen portraits the
    Faces door drew this request, and a uniform tint cannot promise that. */
.home-door-scrim {
    position: absolute;
    inset: 0;
    background: linear-gradient(to top,
        rgba(6, 33, 96, .94) 0%,
        rgba(6, 33, 96, .76) 26%,
        rgba(6, 33, 96, .20) 58%,
        rgba(6, 33, 96, .08) 100%);
}

.home-door-txt {
    position: absolute;
    inset: auto 0 0 0;
    padding: clamp(1rem, 2vw, 1.5rem);
    text-align: center;
}

.home-door-word {
    display: block;
    font: 400 clamp(1.5rem, 2.4vw, 2rem)/1.1 var(--memorial-serif);
    color: #fff;
    transition: color .25s ease;
}

/*  #FFD700 on the navy foot of the scrim measures 12.7:1, and this is 24px+
    display type besides — the site gold works here, where .title-gold on white
    cards had to drop to #8B6508 to hold 4.5:1. */
.home-door:hover .home-door-word,
.home-door:focus-visible .home-door-word {
    color: #FFD700;
}

.home-door-sub {
    display: block;
    margin-top: .3rem;
    font: 500 11px/1.2 'Inter', system-ui, sans-serif;
    letter-spacing: .18em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, .78);
}

/*  The picture push is movement; the preference asks for less of it. Colour and
    shadow are not, and stay — the same reading as the memorial's own
    reduced-motion block, which turns the transitions off without turning the
    design off.

    Only the picture needs suppressing now: the card itself no longer moves, and
    its remaining transition is box-shadow. */
@media (prefers-reduced-motion: reduce) {

    .home-door img {
        transition: none;
    }

        .home-door:hover img,
        .home-door:focus-visible img {
            transform: none;
        }
}

/*  ------------------------------------------------------------ from the editor

    Jimmy DeButts' letter for the limited release. The one block of continuous
    prose on a page that is otherwise headings, cards and figures, so it is set
    apart by type rather than by another band of colour: the page already
    alternates white sections with navy ones, and a third ground would read as a
    fourth subject on a homepage cut down to two.

    --memorial-serif, not the site's Inter. The face is already requested at the
    top of Pages/Index.cshtml for the banner's "Never Forgotten", so setting the
    letter in it costs nothing to load and puts the editor's voice in the same
    serif as the memorial he is writing about.

    The measure is written in em and NOT in the `ch` unit it started as. `ch` is
    the width of the digit zero, and in EB Garamond the digits are nothing like
    the lowercase: 62ch measured out a box whose longest rendered line was 121
    characters. Counted properly, by walking a Range over the rendered text rather
    than by dividing widths, this face sets about 3.35 characters per em, so a
    width in em holds a character count steady and scales with the clamp rather
    than drifting against it.

    32em — about 90 characters to a line, 99 at the longest. Derrick, 2026-09-08:
    "the letter can be wider than the articles column", then "make the letter from
    Jimmy wider so it reads like an official letter not a news article."

    That is the whole point of the width, and it is a deliberate exception to a
    rule this release otherwise enforces. A narrow measure is what a NEWSPAPER
    column is: it exists so an eye can run down a tall stack of type. A letter is
    not read that way — it is a page of correspondence, and correspondence sets
    its text across the sheet. A business letter runs about 6.5 inches of type,
    which lands near ninety characters; at 68 this read as one more article column
    with a signature under it.

    It therefore exceeds WCAG 2.2 SC 1.4.8's 80-character ceiling, knowingly. That
    criterion is AAA rather than the AA this site is held to, it applies to blocks
    of text rather than a six-paragraph letter, and its remedy — a mechanism to
    narrow the column — is the browser's own zoom and reader mode, both of which
    work on this page. The articles stay at 68.

    The serif is declared here, on the element the measure is written on, rather
    than on .home-letter-body where the prose lives — an em width has to resolve
    against the font it is measuring. The kicker, the name and the role each
    state Inter for themselves, so moving the family up does not reach them. */
.home-letter {
    max-width: 32em;
    margin-inline: auto;
    text-align: center;
    font: 400 clamp(1.08rem, 1.4vw, 1.26rem)/1.75 var(--memorial-serif);
}

.home-letter-kicker {
    font: 600 clamp(10px, 1vw, 12px)/1 'Inter', system-ui, sans-serif;
    letter-spacing: .28em;
    text-transform: uppercase;
    color: #6b7280;
}

/*  The banner's gold rule, centred and unchanged otherwise — same 64x2, same
    #FFD700. It is the mark this page uses to open a memorial voice, and the
    letter is the second place that happens. */
.home-letter-rule {
    height: 2px;
    width: 64px;
    margin: .9rem auto clamp(1.5rem, 3vw, 2rem);
    border: 0;
    border-radius: 1px;
    background: #FFD700;
}

/*  Size and leading are inherited from .home-letter above, which is where the
    measure is written and therefore where the family has to be. 1.75 leading
    rather than the body's 1.65: a serif at this size, centred, needs the extra
    to keep six paragraphs from setting as one block. */
.home-letter-body {
    color: #374151;
}

    .home-letter-body p + p {
        margin-top: 1.1rem;
    }

/*  His last line before the signature. Small caps would be a different sentence;
    this is the same words, given the space a closing line is read with. */
.home-letter-close {
    font-style: italic;
    color: #062160;
}

.home-letter-sign {
    margin-top: clamp(1.75rem, 3.5vw, 2.5rem);
    display: flex;
    flex-direction: column;
    align-items: center;
}

/*  The scan is a photograph of his signature on cream stock. The paper was
    mapped to transparency and the strokes to #16234B — the ink's own navy, a
    half-step off the site's #062160 because it is ink and not a UI colour — so
    the mark sits on the page's white rather than in a cream rectangle. The alpha
    is taken from the scan's luminance rather than keyed on the paper colour,
    which is what keeps the hairline ends of the strokes from fringing.

    Sized in vw between two pixel bounds so it stays a signature: unbounded, a
    738px file on a wide viewport reads as a logo. */
.home-letter-mark {
    display: block;
    width: clamp(190px, 24vw, 268px);
    height: auto;
    margin-bottom: .4rem;
}

.home-letter-name {
    font: 600 .9rem/1.2 'Inter', system-ui, sans-serif;
    letter-spacing: .04em;
    color: #062160;
}

.home-letter-role {
    margin-top: .15rem;
    font: 400 .82rem/1.2 'Inter', system-ui, sans-serif;
    color: #6b7280;
}

/*  ------------------------------------------- the emblem either side of it

    Derrick, 2026-09-09: "maybe we add the emblem in gray on either side of the
    from the editor to fill the space? make it tasteful and subtle but still
    balanced and nice."

    The section is the positioning context rather than a wrapper div, so the two
    marks measure from the same box the letter is centred in and the gutters stay
    equal without arithmetic.

    invert(1) is what makes them grey: the file is white artwork over alpha, drawn
    for the dark hero, and inverting turns the strokes black while leaving the
    transparency alone. Held at .07 so it reads as a watermark in the paper rather
    than as a second thing on the page — anything darker and the eye leaves the
    letter to look at it, which is the opposite of filling space.

    NOT mirrored on the right. The emblem carries the words NEVER FORGET, and a
    flipped copy sets them backwards; at this opacity almost nobody would read
    them, which is not a reason to print them wrong. */
.home-letter-flourish {
    display: none;
    position: absolute;
    top: 50%;
    width: clamp(176px, 15vw, 244px);
    height: auto;
    transform: translateY(-50%);
    filter: invert(1);
    opacity: .07;
    pointer-events: none;
    user-select: none;
}

.home-letter-flourish--start {
    inset-inline-start: 0;
}

.home-letter-flourish--end {
    inset-inline-end: 0;
}

/*  1280px, not the 1024px the rest of the letter switches at. At 1024 the
    container leaves about 160px a side once the 32em column is placed, and a
    mark that size would be crowding the text rather than balancing it. Below
    this the letter keeps the page to itself. */
@media (min-width: 1280px) {
    .home-letter-frame {
        position: relative;
    }

    .home-letter-flourish {
        display: block;
    }
}

/*  Forced-colours throws the filter and the opacity away and would paint two
    solid emblems beside the letter. Decoration is the first thing that should go
    in a mode a reader turned on to see the words. */
@media (forced-colors: active) {
    .home-letter-flourish {
        display: none;
    }
}

/*  ------------------------------------------------ the letter, ranged left

    Desktop reads it as correspondence rather than as a centred pull quote.
    Derrick, 2026-09-08: "make it left justified so it reads like a formal letter
    in desktop mode." Everything ranges together — kicker, rule, prose and the
    signature — because a letter with a centred heading over left-set prose reads
    as a page with a title, which is the thing it is not.

    Left, NOT justified: text-align:justify on a 79-character serif measure opens
    rivers of white between the words, and the release whose accessibility pass
    this rides on is not the place to introduce them. A ragged right is also what
    makes a letter look typed rather than set.

    LAST in the sheet on purpose. A media query carries no extra specificity, so
    `margin-inline: 0` below only beats the `margin: .9rem auto` shorthand on
    .home-letter-rule by coming after it. Written above that rule — where it
    reads more naturally — the rule wins and the gold dash stays centred over
    left-set prose, which is exactly the mistake this block exists to avoid.

    1024px is where .home-memorial-scrim already flattens, so the page keeps ONE
    definition of where desktop begins. Below it the block stays centred, which
    is what a 343px column wants and what the request scoped itself to. */
@media (min-width: 1024px) {
    .home-letter {
        text-align: left;
    }

        .home-letter-rule {
            margin-inline: 0;
        }

        .home-letter-sign {
            align-items: flex-start;
        }
}
