/* === 人生軌道 (Life Flow) ===
 *
 * Replaces the old fixed-scale multi-track board. Layout is driven by content,
 * not by a pixels-per-year constant, so a sparse life doesn't become thousands
 * of pixels of empty canvas.
 *
 * Structure of one row:
 *   .flow-row
 *     .flow-rails   fixed-width gutter, one cell per concurrent period
 *     .flow-main    the event card / chapter band / gap label
 */

/* --- Sticky context bar: where you are, and what was running then --- */
.flow-context {
    flex-shrink: 0;
    padding: 10px 16px;
    background: var(--bg-paper);
    border-bottom: 1px solid var(--line-color);
    min-height: 62px;
}

.ctx-when {
    display: flex;
    align-items: baseline;
    gap: 8px;
    flex-wrap: wrap;
}

.ctx-when strong {
    font-family: var(--font-heading);
    font-size: 1.25rem;
    font-variant-numeric: lining-nums;
    color: var(--ink-primary);
}

.ctx-when span {
    font-size: 0.78rem;
    color: var(--ink-secondary);
}

.ctx-chapter {
    padding: 2px 9px;
    border-radius: 10px;
    font-weight: 700;
    color: var(--chapter) !important;
    border: 1px solid var(--chapter);
}

.ctx-active {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    margin-top: 5px;
}

.ctx-label {
    font-size: 0.72rem;
    color: var(--ink-secondary);
}

.ctx-label.empty {
    opacity: 0.6;
}

/* Chips carry the same colour as the rail, which is how you map line → name */
.ctx-chip {
    font-size: 0.72rem;
    padding: 2px 9px;
    border-radius: 10px;
    color: var(--rail);
    border: 1px solid currentColor;
    background: transparent;
    white-space: nowrap;
}

/* --- Category filter --- */
.flow-filters {
    flex-shrink: 0;
    display: flex;
    gap: 6px;
    overflow-x: auto;
    padding: 10px 16px;
    background: var(--bg-paper);
    border-bottom: 1px solid var(--line-color);
    scrollbar-width: none;
}

.flow-filters::-webkit-scrollbar {
    display: none;
}

.flow-filter-btn {
    flex-shrink: 0;
    padding: 6px 12px;
    min-height: 34px;
    border-radius: 17px;
    border: 1px solid var(--line-color);
    background: transparent;
    color: var(--ink-secondary);
    font-family: inherit;
    font-size: 0.78rem;
    cursor: pointer;
    opacity: 0.5;
    transition: opacity 0.15s, border-color 0.15s;
}

.flow-filter-btn.active {
    opacity: 1;
    color: var(--chip);
    border-color: currentColor;
    font-weight: 700;
}

/* --- Scroll area --- */
/* --- The chart ---------------------------------------------------------
 *
 * The Y axis is time. A block's height is how long the thing actually lasted,
 * so two things running at once are two blocks covering the same band of
 * screen — overlap you can see rather than read.
 *
 *   .flow-chart
 *     .flow-head     sticky category labels
 *     .flow-body
 *       .flow-years  sticky-left year axis
 *       .flow-plot   chapters / gaps / blocks / milestones, absolutely placed
 */
.flow-body-wrap {
    flex: 1;
    display: flex;
    min-height: 0;
    position: relative;
}

/* Edge fades marking that more categories exist off-screen. Sat on the wrapper,
   not inside .flow-scroll — a gradient inside the scroller would slide away
   with the content it is meant to be pointing at.
   `right` clears the 22px minimap plus its 2px margin. */
.flow-body-wrap::before,
.flow-body-wrap::after {
    content: '';
    position: absolute;
    top: 0;
    bottom: 0;
    width: 26px;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.18s;
    z-index: 6;
}

.flow-body-wrap::before {
    left: 0;
    background: linear-gradient(to right, var(--bg-paper), transparent);
}

.flow-body-wrap::after {
    right: 24px;
    background: linear-gradient(to left, var(--bg-paper), transparent);
}

.flow-body-wrap.has-overflow-left::before,
.flow-body-wrap.has-overflow-right::after {
    opacity: 1;
}

.flow-scroll {
    flex: 1;
    min-width: 0;
    overflow: auto;
    /* Reserve the vertical scrollbar up front. renderFlow() measures clientWidth
       to size the columns, and it does so while this box is still empty — once
       the tall chart lands the scrollbar appears, clientWidth shrinks ~15px, and
       every column ends up too wide, leaving a permanent phantom horizontal
       scroll. Reserving the gutter keeps that measurement honest. (No-op where
       scrollbars are overlays, i.e. touch devices.) */
    scrollbar-gutter: stable;
    padding: 0 6px calc(78px + env(safe-area-inset-bottom)) 6px;
    -webkit-overflow-scrolling: touch;
    position: relative;
    /* Claim pinch for the time scale; the browser keeps both pan axes. */
    touch-action: pan-x pan-y;
}

.flow-chart {
    position: relative;
    min-width: 100%;
}

.flow-head {
    position: sticky;
    top: 0;
    z-index: 4;
    height: 26px;
    background: var(--bg-paper);
    border-bottom: 1px solid var(--line-color);
}

/* Pinned mask over the year-gutter column, so a sideways scroll never slides a
   category label into the strip above the year axis. */
.flow-head-corner {
    position: sticky;
    left: 0;
    z-index: 5;
    height: 100%;
    background: var(--bg-paper);
}

.flow-head-cell {
    position: absolute;
    top: 4px;
    font-size: 0.7rem;
    letter-spacing: 0.04em;
    color: var(--chip, #666);
    text-align: center;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.flow-body {
    display: flex;
    align-items: flex-start;
    position: relative;
}

/* --- Year axis --- */
.flow-years {
    position: sticky;
    left: 0;
    z-index: 3;
    flex: 0 0 38px;
    width: 38px;
    background: var(--bg-paper);
}

.flow-year {
    position: absolute;
    left: 0;
    transform: translateY(-50%);
    font-family: var(--font-heading);
    font-size: 0.85rem;
    color: var(--ink-secondary);
    opacity: 0.8;
    font-variant-numeric: lining-nums;
}

/* --- Plot --- */
.flow-plot {
    position: relative;
    flex: 0 0 auto;
}

/* Chapters sit behind everything as a tinted band */
.flow-chapter-band {
    position: absolute;
    left: 0;
    z-index: 0;
    background: color-mix(in srgb, var(--chapter) 9%, transparent);
    border-radius: 2px;
    pointer-events: none;
}

.fcb-title {
    position: absolute;
    top: 3px;
    right: 4px;
    font-family: var(--font-heading);
    font-style: italic;
    font-size: 0.63rem;
    letter-spacing: 0.04em;
    color: var(--chapter);
    opacity: 0.7;
    white-space: nowrap;
}

/* A collapsed stretch of nothing — a quiet break in the ruling, no commentary */
.flow-gap-band {
    position: absolute;
    left: 0;
    right: 0;
    z-index: 1;
    pointer-events: none;
}

/* Deliberately draws nothing: the compressed space itself says time passed.
   A dashed rule here was one of several competing line styles. */

/* --- Period blocks: the whole point of this view --- */
.flow-block {
    position: absolute;
    z-index: 2;
    padding: 4px 6px;
    border: none;
    border-left: 3px solid var(--rail);
    border-radius: 4px;
    background: color-mix(in srgb, var(--rail) 20%, var(--bg-paper));
    color: var(--ink-primary);
    text-align: left;
    overflow: hidden;
    cursor: pointer;
    display: flex;
    flex-direction: column;
    gap: 2px;
    transition: filter 0.15s;
}

.flow-block:hover,
.flow-block:focus-visible {
    filter: brightness(0.96);
    outline: none;
}

/* Still running: the block dissolves at the foot rather than being capped by
   yet another dashed line. */
.flow-block.is-open {
    -webkit-mask-image: linear-gradient(to bottom, #000 78%, transparent);
    mask-image: linear-gradient(to bottom, #000 78%, transparent);
}

.fb-title {
    font-size: 0.78rem;
    line-height: 1.25;
    font-weight: 600;
    color: color-mix(in srgb, var(--rail) 75%, var(--ink-primary));
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    word-break: break-word;
}

/* Too short to letter — the bar itself is the information */
.flow-block.is-bare {
    padding: 0;
}

.fb-dur {
    font-size: 0.63rem;
    color: var(--ink-secondary);
    opacity: 0.85;
}

/* --- Moments: single-day events, anchored in their own category column --- */
/* The visible dot stays 7px, but the button box around it is finger-sized.
   It used to be 0x0, leaving only the dot itself tappable — a 7x7 target
   against a 44x44 guideline. Kept deliberately shorter than 44 vertically so
   neighbouring events in a dense column do not swallow each other's taps;
   the label beside it carries the rest of the target area. */
.flow-moment {
    position: absolute;
    z-index: 3;
    width: 36px;
    height: 28px;
    margin: -14px 0 0 -18px;
    padding: 0;
    border: none;
    background: transparent;
    cursor: pointer;
}

.fm-dot {
    left: 50%;
    top: 50%;
    margin: -3.5px 0 0 -3.5px;
}

.fm-dot {
    position: absolute;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--rail);
}

/* The name sits UNDER its dot and is clamped to its own column, so it can
   never drift over a neighbouring category the way the old free-floating
   side label did. It wraps to two lines rather than growing sideways. */
.flow-dot-label {
    position: absolute;
    z-index: 4;
    padding: 2px 2px 5px;
    font-size: 0.7rem;
    line-height: 1.25;
    color: var(--rail);
    text-align: center;
    border: none;
    background: transparent;
    font-family: inherit;
    cursor: pointer;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    word-break: break-word;
}

.flow-dot-label:focus-visible {
    outline: 2px solid var(--accent-gold);
    outline-offset: -2px;
}

/* A dot standing for more than one event reads as a slightly heavier ring */
.flow-moment.is-group .fm-dot {
    width: 9px;
    height: 9px;
    margin: -4.5px 0 0 -4.5px;
    box-shadow: 0 0 0 2px var(--bg-paper), 0 0 0 3px var(--rail);
}


/* --- Today --- */
.flow-today {
    position: absolute;
    left: 0;
    right: 0;
    z-index: 5;
    height: 0;
    border-top: 1.5px solid var(--ink-primary);
    pointer-events: none;
}

.flow-today span {
    position: absolute;
    right: 0;
    top: -8px;
    padding: 0 5px;
    background: var(--bg-paper);
    font-family: var(--font-heading);
    font-size: 0.63rem;
    color: var(--ink-primary);
    letter-spacing: 0.08em;
}

/* --- Detail sheet ------------------------------------------------------ */
.flow-detail {
    position: absolute;
    inset: 0;
    z-index: 40;
    background: rgba(0, 0, 0, 0.35);
    display: none;
    align-items: flex-end;
}

.flow-detail.open {
    display: flex;
}

.fd-sheet {
    width: 100%;
    max-height: 82%;
    overflow-y: auto;
    background: var(--bg-paper);
    border-radius: 16px 16px 0 0;
    box-shadow: 0 -6px 24px rgba(0, 0, 0, 0.18);
    animation: fdUp 0.18s ease-out;
}

@keyframes fdUp {
    from { transform: translateY(14px); opacity: 0.6; }
    to   { transform: translateY(0);    opacity: 1; }
}

.fd-body {
    padding: 18px 18px calc(20px + env(safe-area-inset-bottom));
}

.fd-head {
    border-left: 3px solid var(--rail);
    padding-left: 10px;
    margin-bottom: 18px;
}

.fd-title {
    font-size: 1.1rem;
    font-weight: 600;
    color: var(--ink-primary);
    margin-bottom: 4px;
}

.fd-meta {
    font-size: 0.75rem;
    color: var(--ink-secondary);
    line-height: 1.6;
}

.fd-chapter {
    padding: 1px 7px;
    border-radius: 9px;
    border: 1px solid var(--line-color);
}

.fd-desc {
    margin-top: 8px;
    font-size: 0.85rem;
    line-height: 1.65;
    color: var(--ink-secondary);
}

.fd-section {
    margin-bottom: 16px;
}

.fd-section h4 {
    margin: 0 0 8px;
    font-size: 0.76rem;
    letter-spacing: 0.08em;
    color: var(--ink-secondary);
    font-weight: 600;
}

.fd-list {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.fd-row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 10px;
    padding: 7px 10px;
    border-left: 3px solid var(--rail);
    border-radius: 4px;
    background: color-mix(in srgb, var(--rail) 9%, transparent);
}

.fd-row-title {
    font-size: 0.85rem;
    color: var(--ink-primary);
}

.fd-row-meta {
    font-size: 0.68rem;
    color: var(--ink-secondary);
    white-space: nowrap;
}

.fd-empty {
    margin: 0;
    font-size: 0.8rem;
    color: var(--ink-secondary);
    opacity: 0.8;
}

.fd-actions {
    display: flex;
    gap: 10px;
    margin-top: 20px;
}

.fd-actions button {
    flex: 1;
}
/* --- Empty states --- */
.flow-empty {
    padding: 40px 8px;
    text-align: center;
    color: var(--ink-secondary);
}

.flow-empty.subtle {
    padding: 24px 8px 8px;
    opacity: 0.85;
}

.flow-empty p {
    margin: 0 0 8px;
    font-size: 0.95rem;
}

.flow-empty .sub {
    font-size: 0.82rem;
    line-height: 1.6;
    opacity: 0.85;
}

/* --- Chapter manager --- */
.chapter-list {
    margin-bottom: 20px;
}

.chapter-row {
    padding: 10px 12px;
    margin-bottom: 8px;
    border-radius: 8px;
    border: 1px solid var(--line-color);
    border-left: 4px solid var(--chapter);
    cursor: pointer;
    transition: border-color 0.15s;
}

.chapter-row:hover {
    border-color: var(--chapter);
}

.chapter-row-title {
    font-weight: 700;
    font-size: 0.95rem;
}

.chapter-row-meta {
    margin-top: 2px;
    font-size: 0.74rem;
    color: var(--ink-secondary);
    font-variant-numeric: lining-nums;
}

.chapter-form {
    border-top: 1px dashed var(--line-color);
    padding-top: 18px;
}

/* --- Goals: dashed markers below the "today" line ---------------------- */
/* The marker's box is finger-sized; the dashed line is drawn down its middle by
   a pseudo-element. Putting the border on the box itself would pin the line to
   the top edge, i.e. 11px above the date it marks. */
.flow-goal {
    position: absolute;
    left: 0;
    z-index: 4;
    height: 22px;
    margin-top: -11px;
    padding: 0;
    border: none;
    background: transparent;
    opacity: 0.7;
    cursor: pointer;
    transition: opacity 0.15s;
}

.flow-goal::before {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    border-top: 1.5px dashed var(--rail);
}

.flow-goal:hover,
.flow-goal:focus-visible {
    opacity: 1;
    outline: none;
}

/* Hollow dot, so a goal never reads as something that already happened */
.fg-dot {
    position: absolute;
    left: -4px;
    top: 50%;
    margin-top: -4px;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    border: 1.5px solid var(--rail);
    background: var(--bg-paper);
}

.fg-label {
    position: absolute;
    right: 2px;
    top: 50%;
    transform: translateY(-50%);
    display: flex;
    align-items: baseline;
    gap: 5px;
    padding: 0 5px;
    background: var(--bg-paper);
    font-size: 0.7rem;
    color: var(--rail);
    white-space: nowrap;
    max-width: 78%;
    overflow: hidden;
}

.fg-label em {
    font-style: normal;
    font-size: 0.63rem;
    opacity: 0.75;
    font-variant-numeric: lining-nums;
}

/* --- Dark mode --- */
[data-theme="dark"] .flow-context,
[data-theme="dark"] .flow-filters {
    background: var(--bg-paper);
    border-color: var(--line-color);
}

/* Blocks tint a dark surface instead of a light one */
[data-theme="dark"] .flow-block {
    background: color-mix(in srgb, var(--rail) 34%, #232323);
}

[data-theme="dark"] .fb-title,
[data-theme="dark"] .flow-side-label,
[data-theme="dark"] .flow-head-cell {
    color: color-mix(in srgb, var(--rail) 30%, #ece7e1);
}

[data-theme="dark"] .flow-chapter-band {
    background: color-mix(in srgb, var(--chapter) 12%, transparent);
}

[data-theme="dark"] .flow-today {
    border-top-color: var(--ink-primary);
}

[data-theme="dark"] .fd-sheet {
    box-shadow: 0 -6px 24px rgba(0, 0, 0, 0.6);
}

/* color-mix is widely supported, but keep a readable fallback if it isn't */
@supports not (background: color-mix(in srgb, red 8%, transparent)) {
    .flow-chapter-band { background: var(--bg-paper-dark); }
    .flow-block { background: var(--bg-paper-dark); }
    .fb-title { color: var(--rail); }
    .fd-row { background: var(--bg-paper-dark); }
}

[data-theme="dark"] .fg-dot,
[data-theme="dark"] .fg-label {
    background: var(--bg-paper);
}

/* --- Zoom controls --- */
.flow-header-actions {
    display: flex;
    align-items: center;
    gap: 4px;
    margin-left: auto;
}

.flow-zoom-btn {
    width: 26px;
    height: 26px;
    border: 1px solid var(--line-color);
    border-radius: 6px;
    background: var(--bg-paper);
    color: var(--ink-primary);
    font-size: 0.85rem;
    line-height: 1;
    cursor: pointer;
}

.flow-zoom-btn:disabled { opacity: 0.3; cursor: default; }

.flow-zoom-level {
    min-width: 26px;
    text-align: center;
    font-size: 0.68rem;
    color: var(--ink-secondary);
    font-variant-numeric: lining-nums;
}

/* --- Minimap: the whole life as a 22px strip ---------------------------- */
.flow-minimap {
    position: relative;
    flex: 0 0 22px;
    width: 22px;
    margin: 0 2px calc(74px + env(safe-area-inset-bottom)) 0;
    border-left: 1px solid var(--line-color);
    background: var(--bg-paper);
    cursor: pointer;
    touch-action: none;
}

.flow-minimap:focus-visible {
    outline: 2px solid var(--accent-gold);
    outline-offset: -2px;
}

.mm-marks {
    position: absolute;
    inset: 0;
}

.mm-chapter {
    position: absolute;
    left: 0;
    right: 0;
    background: color-mix(in srgb, var(--chapter) 16%, transparent);
}

.mm-bar {
    position: absolute;
    border-radius: 1px;
    background: var(--rail);
    opacity: 0.75;
}

.mm-today {
    position: absolute;
    left: 0;
    right: 0;
    height: 0;
    border-top: 1px solid var(--ink-primary);
}

.mm-goal {
    position: absolute;
    left: 50%;
    width: 4px;
    height: 4px;
    margin: -2px 0 0 -2px;
    border-radius: 50%;
    border: 1px solid var(--accent-gold);
    background: var(--bg-paper);
}

/* The slice you are looking at right now */
.mm-viewport {
    position: absolute;
    left: 0;
    right: 0;
    border: 1px solid var(--ink-secondary);
    border-radius: 2px;
    background: color-mix(in srgb, var(--ink-primary) 10%, transparent);
    pointer-events: none;
    transition: top 0.08s linear;
}

[data-theme="dark"] .mm-viewport {
    border-color: var(--ink-secondary);
    background: rgba(255, 255, 255, 0.12);
}

@supports not (background: color-mix(in srgb, red 8%, transparent)) {
    .mm-viewport { background: rgba(120, 120, 120, 0.25); }
}

/* Rows in the merged-dot sheet are buttons, not static rows */
.fd-row-btn {
    width: 100%;
    font-family: inherit;
    cursor: pointer;
    text-align: left;
}

.fd-row-btn:hover { filter: brightness(0.97); }

/* Short events on the strip: a hairline tick rather than a bar */
.mm-tick {
    position: absolute;
    height: 2px;
    border-radius: 1px;
    background: var(--rail);
    opacity: 0.6;
}

/* --- Context bar: the events currently on screen ----------------------- */
.ctx-events {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-top: 5px;
    overflow-x: auto;
    scrollbar-width: none;
}

.ctx-events::-webkit-scrollbar { display: none; }

/* Lighter than a period chip — these are moments, not phases */
.ctx-event {
    flex-shrink: 0;
    position: relative;
    padding: 1px 8px 1px 14px;
    font-size: 0.68rem;
    color: var(--ink-primary);
    white-space: nowrap;
}

.ctx-event::before {
    content: '';
    position: absolute;
    left: 4px;
    top: 50%;
    width: 5px;
    height: 5px;
    margin-top: -2.5px;
    border-radius: 50%;
    background: var(--rail);
}

.ctx-more {
    flex-shrink: 0;
    font-size: 0.68rem;
    color: var(--ink-secondary);
    opacity: 0.8;
}
