/* ============================================================
   ABC article figures
   ------------------------------------------------------------
   Diagrams embedded in articles. Each one is an inline SVG, so
   it stays sharp at any size, weighs a few kilobytes, and can be
   animated and restyled from here rather than re-exported.

   THE RULE THIS FILE FOLLOWS: the animation always ends on the
   state that carries the meaning, and every figure is drawn in
   that finished state by default. Motion is added by a class the
   script puts on when the figure scrolls into view. So a reader
   with JavaScript off, a reader who has asked for less motion, a
   printed page and a screenshot all get the complete diagram --
   they lose the reveal, not the information. A figure that is
   blank until a script runs is not a diagram, it is a liability.
   ============================================================ */

.abc-fig {
    margin: 40px 0;
    padding: 0;
}

.abc-fig-media {
    position: relative;
    background: #F7F8FC;
    border: 1px solid rgba(2, 0, 58, 0.10);
    border-radius: 10px;
    padding: 26px 24px;
    overflow: hidden;
}

.abc-fig-media svg {
    display: block;
    width: 100%;
    height: auto;
    /* The drawings are laid out at their viewBox width; this stops a
       wide one from stretching to a silly size in a full-bleed layout
       and leaving its labels adrift in white space. */
    max-width: 720px;
    margin: 0 auto;
}

.abc-fig-title {
    font-family: var(--mono);
    font-size: 11px;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--blue);
    margin-bottom: 14px;
}

.abc-fig figcaption {
    font-family: var(--sans);
    font-size: 14px;
    line-height: 1.65;
    color: var(--gray);
    margin-top: 14px;
    padding-left: 14px;
    border-left: 2px solid rgba(0, 51, 255, 0.35);
}

.abc-fig figcaption strong {
    color: var(--dark-text);
    font-weight: 600;
}

/* A figure that states a number states where the number came from,
   in the figure itself, because figures get screenshotted and passed
   around without the paragraph that qualified them. */
.abc-fig-source {
    display: block;
    font-family: var(--mono);
    font-size: 11px;
    line-height: 1.6;
    color: rgba(107, 114, 128, 0.95);
    margin-top: 9px;
}

/* ── Shared drawing vocabulary ─────────────────────────────────
   Set here rather than on each <svg> so the whole set restyles at
   once and no single drawing can drift off-brand. */
.abc-fig svg text {
    font-family: var(--sans);
    fill: #0A0020;
}
.abc-fig .f-label  { font-size: 13px; }
.abc-fig .f-small  { font-size: 11px; fill: #6B7280; }
.abc-fig .f-mono   { font-family: var(--mono); font-size: 11px; letter-spacing: .06em; fill: #6B7280; }
.abc-fig .f-head   { font-family: var(--mono); font-size: 13px; fill: #0600AB; }
.abc-fig .f-strong { font-weight: 600; }

/* Coloured labels. These MUST be classes, and a drawing must never
   reach for fill="#B3261E" on a <text> instead.

   A presentation attribute has a specificity of zero, so every one of
   the rules above beats it. Thirteen labels across this set were written
   with fill="#B3261E" meaning "this is the warning", and every one of
   them rendered in the same grey as the label beside it -- silently, with
   no error anywhere, and invisibly to both the layout checker (which
   measures boxes) and the state harness (which measures opacity). It was
   found by asking the browser what colour it had actually used.

   Declared last so they win against .f-small and .f-mono, which they tie
   with on specificity. The figure harness refuses to build an SVG that
   puts a fill attribute on a <text>, so this cannot quietly come back. */
.abc-fig .f-t-warn   { fill: #B3261E; }
.abc-fig .f-t-good   { fill: #1B7F5A; }
.abc-fig .f-t-accent { fill: #6B49E0; }
.abc-fig .f-t-blue   { fill: #0033FF; }

.abc-fig .f-stroke      { stroke: #0033FF; fill: none; stroke-width: 1.6; }
.abc-fig .f-stroke-soft { stroke: rgba(2,0,58,0.22); fill: none; stroke-width: 1.2; }
.abc-fig .f-fill        { fill: #0033FF; }
.abc-fig .f-fill-soft   { fill: rgba(0,51,255,0.10); }
.abc-fig .f-accent      { fill: #977DFF; }
.abc-fig .f-accent-soft { fill: rgba(151,125,255,0.20); }
.abc-fig .f-warn        { fill: #B3261E; }
/* The two soft state fills are deliberately stronger than the other
   -soft tints. They are the ones that get laid over .f-tissue, and at
   0.12-0.14 alpha a green over that pink came out grey -- which is
   exactly the wrong signal from a fill whose entire job is to say
   "this part lived". */
.abc-fig .f-warn-soft   { fill: rgba(179,38,30,0.20); }
.abc-fig .f-good        { fill: #1B7F5A; }
.abc-fig .f-good-soft   { fill: rgba(27,127,90,0.24); }
.abc-fig .f-tissue      { fill: #F2E6EE; }
.abc-fig .f-paper       { fill: #FFFFFF; }

/* Outline versions of the three state colours. A drawing that means
   "this survived" and one that means "this died" should not reach for a
   hex value of their own each time; one of them would drift. */
.abc-fig .f-stroke-good   { stroke: #1B7F5A; fill: none; stroke-width: 1.6; }
.abc-fig .f-stroke-warn   { stroke: #B3261E; fill: none; stroke-width: 1.6; }
.abc-fig .f-stroke-accent { stroke: #977DFF; fill: none; stroke-width: 1.6; }

/* A dashed line means "not a thing, a distance or a boundary".
   NEVER put .f-dash on an element that also has .f-anim-draw: the draw
   animation owns stroke-dasharray, and the two fight. Use one or the
   other. */
.abc-fig .f-dash { stroke-dasharray: 4 5; }

/* ── Motion ────────────────────────────────────────────────────
   Nothing below changes what the diagram says. Every rule here is
   a transition FROM an altered state back TO the state already in
   the markup, applied only once .is-live has been added, so the
   default rendering is the finished one. */
.abc-fig-media.is-live .f-anim-draw {
    stroke-dasharray: var(--len, 400);
    stroke-dashoffset: var(--len, 400);
    animation: abc-fig-draw 1.1s ease forwards;
    animation-delay: var(--delay, 0s);
}
@keyframes abc-fig-draw { to { stroke-dashoffset: 0; } }

.abc-fig-media.is-live .f-anim-in {
    opacity: 0;
    animation: abc-fig-in .5s ease forwards;
    animation-delay: var(--delay, 0s);
}
@keyframes abc-fig-in { to { opacity: 1; } }

.abc-fig-media.is-live .f-anim-rise {
    opacity: 0;
    transform: translateY(10px);
    animation: abc-fig-rise .55s cubic-bezier(.2, .7, .3, 1) forwards;
    animation-delay: var(--delay, 0s);
}
@keyframes abc-fig-rise { to { opacity: 1; transform: translateY(0); } }

.abc-fig-media.is-live .f-anim-grow {
    transform: scaleY(0);
    transform-origin: var(--origin, 50% 100%);
    animation: abc-fig-grow .7s cubic-bezier(.2, .7, .3, 1) forwards;
    animation-delay: var(--delay, 0s);
}
@keyframes abc-fig-grow { to { transform: scaleY(1); } }

/* A pulse marks the one element a figure wants you to look at. It
   repeats, so unlike the reveals above it is capped: three beats,
   then it stops and leaves the figure quiet. */
.abc-fig-media.is-live .f-anim-pulse {
    animation: abc-fig-pulse 1.6s ease-in-out 3;
    animation-delay: var(--delay, 0s);
    transform-box: fill-box;
    transform-origin: center;
}
@keyframes abc-fig-pulse {
    0%, 100% { opacity: 1; transform: scale(1); }
    50%      { opacity: .55; transform: scale(1.06); }
}

/* Asked for less motion, or printing: the figure is simply drawn.
   This wins because it is the same specificity and comes later --
   and because the script also declines to add .is-live at all, so
   this is a second line of defence, not the only one. */
@media (prefers-reduced-motion: reduce) {
    .abc-fig-media.is-live .f-anim-draw,
    .abc-fig-media.is-live .f-anim-in,
    .abc-fig-media.is-live .f-anim-rise,
    .abc-fig-media.is-live .f-anim-grow,
    .abc-fig-media.is-live .f-anim-pulse {
        animation: none;
        opacity: 1;
        transform: none;
        stroke-dashoffset: 0;
    }
}

@media print {
    .abc-fig-media { background: none; border-color: #999; }
    .abc-fig-media .f-anim-draw,
    .abc-fig-media .f-anim-in,
    .abc-fig-media .f-anim-rise,
    .abc-fig-media .f-anim-grow,
    .abc-fig-media .f-anim-pulse {
        animation: none !important;
        opacity: 1 !important;
        transform: none !important;
        stroke-dashoffset: 0 !important;
    }
}

@media (max-width: 600px) {
    .abc-fig { margin: 30px 0; }
    .abc-fig-media { padding: 18px 14px; }
    /* The drawings are laid out for about 700px. Below roughly 420 the
       labels fall under 9px, which is not a diagram any more, so the
       figure becomes a pannable strip instead of shrinking further.
       Hiding it would take the description away from screen readers
       too, which is a worse answer than a sideways swipe. */
    .abc-fig-media { overflow-x: auto; -webkit-overflow-scrolling: touch; }
    .abc-fig-media svg { min-width: 440px; }
    .abc-fig-media::after {
        content: "swipe to see the whole diagram \2192";
        display: block;
        font-family: var(--mono);
        font-size: 10px;
        letter-spacing: .05em;
        color: rgba(107,114,128,0.85);
        padding-top: 8px;
    }
}
