daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

flow.css (12277B)


      1 /* ============================================================================
      2    Flow — native, on-theme flowcharts.
      3 
      4    These replace the old ```mermaid fences, which never rendered (Shiki has no
      5    mermaid grammar, so a fence printed its own source as a dead code listing).
      6    Nothing here is JavaScript and nothing fetches: a flow is hand-authored HTML
      7    (or inline SVG) drawn straight onto the page at build time.
      8 
      9    A flow reads as *terminal art*: the same dark plate the code panes ride, in
     10    both site themes, so a diagram sits in the same register as the listings it
     11    sits between (see prose.css — "terminal output pasted into a printed
     12    document"). The wrapper carries `.plate` (pins the Rosé Pine night palette
     13    for its subtree) and `.corners` (the cyberdeck brackets), exactly like a
     14    code pane, so every accent below — `--foam`, `--iris`, `--gold`, `--love`,
     15    `--pine` — resolves to its night value on the cream page without a single
     16    hardcoded hex.
     17 
     18    Two primitives, one look:
     19      • CSS-flow  — ranks of `.flow-node` boxes joined by `.flow-edge`
     20        connectors. Flexbox does the layout; there are no coordinates to get
     21        wrong. Use it for linear chains, decision fan-outs and merges.
     22      • SVG-flow  — an inline `<svg class="flow-svg">` using the shared node /
     23        edge / label classes. Use it only when the graph has back-edges, skip
     24        edges or many-into-one merges that a rank layout would misdraw.
     25    A `.flow-node` box and an `.fnode` rect share the same fill, hairline and
     26    font, so a reader can't tell which engine drew a given box.
     27    ========================================================================== */
     28 
     29 /* ---- Wrapper ------------------------------------------------------------- */
     30 .prose .flow {
     31   position: relative;
     32   margin-block: 1.7rem;
     33   max-width: min(100%, 94ch);
     34   background: var(--plate);
     35   border: 0;
     36   overflow: hidden;
     37   color: var(--fg);
     38 }
     39 /* Runs to the prose measure; a wide flow scrolls inside its own body rather
     40    than pushing the page. */
     41 .prose .flow > * { position: relative; z-index: 2; }
     42 .prose .flow > .scanlines { z-index: 1; opacity: 0.5; }
     43 
     44 /* The caption behaves like a code pane's titlebar: a kind mark at the left,
     45    the flow direction at the right, both in the 9.5px terminal mono. */
     46 .prose .flow__cap {
     47   display: flex;
     48   align-items: center;
     49   justify-content: space-between;
     50   gap: 1rem;
     51   padding: 0.7rem 1.15rem;
     52   border-bottom: 1px solid var(--rule);
     53   font-family: var(--font-term);
     54   font-size: 9.5px;
     55   letter-spacing: 0.18em;
     56   text-transform: uppercase;
     57   line-height: 1;
     58 }
     59 .prose .flow__cap .flow__kind { color: var(--iris); }
     60 .prose .flow__cap .flow__kind::before { content: '◇ '; opacity: 0.8; }
     61 .prose .flow__cap .flow__dir { color: var(--fg-faint); }
     62 
     63 .prose .flow__body {
     64   padding: clamp(1.05rem, 3.2vw, 1.9rem);
     65   overflow-x: auto;
     66 }
     67 
     68 /* ---- CSS-flow: ranks + edges -------------------------------------------- */
     69 .prose .flow__diagram {
     70   display: flex;
     71   align-items: center;
     72   justify-content: center;
     73   gap: 0;
     74   min-width: min-content;
     75 }
     76 .prose .flow__diagram[data-dir='td'] { flex-direction: column; }
     77 .prose .flow__diagram[data-dir='lr'] { flex-direction: row; flex-wrap: wrap; }
     78 
     79 /* A rank is one layer of the graph — a row (TD) or column (LR) of sibling
     80    nodes that sit at the same depth. */
     81 .prose .flow-rank {
     82   display: flex;
     83   gap: clamp(0.7rem, 2.4vw, 1.6rem);
     84   align-items: stretch;
     85   justify-content: center;
     86 }
     87 .prose .flow__diagram[data-dir='lr'] .flow-rank { flex-direction: column; }
     88 
     89 /* ---- Node --------------------------------------------------------------- */
     90 .prose .flow-node {
     91   position: relative;
     92   display: flex;
     93   flex-direction: column;
     94   align-items: center;
     95   justify-content: center;
     96   gap: 0.15rem;
     97   text-align: center;
     98   min-width: 8.5rem;
     99   max-width: 16rem;
    100   padding: 0.6rem 0.9rem;
    101   background: var(--surface);
    102   border: 1px solid var(--rule-hi);
    103   color: var(--text);
    104   font-family: var(--font-term);
    105   font-size: 12.5px;
    106   line-height: 1.32;
    107 }
    108 /* The second line of a node — what was `<br/>` in the mermaid source — reads
    109    as a caption under the label. Mark it up as `<span class="sub">`. */
    110 .prose .flow-node .sub {
    111   color: var(--subtle);
    112   font-size: 10.5px;
    113   letter-spacing: 0.01em;
    114 }
    115 .prose .flow-node code {
    116   font-family: var(--font-term);
    117   font-size: 0.95em;
    118   background: none;
    119   border: 0;
    120   padding: 0;
    121   color: var(--foam);
    122 }
    123 
    124 /* Node roles — colour keyed the same way the SVG kit keys `.fnode` variants. */
    125 .prose .flow-node.is-entry { border-color: var(--iris); }
    126 .prose .flow-node.is-entry::before {
    127   content: 'START';
    128   font-size: 8px; letter-spacing: 0.2em; color: var(--iris);
    129   margin-bottom: 0.1rem;
    130 }
    131 .prose .flow-node.is-goal {
    132   background: color-mix(in srgb, var(--pine) 32%, var(--surface));
    133   border-color: var(--foam);
    134   color: var(--text);
    135 }
    136 .prose .flow-node.is-decision { border-color: var(--gold); }
    137 .prose .flow-node.is-decision::before {
    138   content: '◆ DECIDE';
    139   font-size: 8px; letter-spacing: 0.18em; color: var(--gold);
    140   margin-bottom: 0.15rem;
    141 }
    142 .prose .flow-node.is-note {
    143   background: var(--overlay);
    144   border-style: dashed;
    145   color: var(--subtle);
    146 }
    147 .prose .flow-node.is-danger { border-color: var(--love); }
    148 .prose .flow-node.is-danger::before {
    149   content: '! ';
    150   color: var(--love);
    151 }
    152 
    153 /* ---- Edge (connector) --------------------------------------------------- */
    154 .prose .flow-edge {
    155   position: relative;
    156   align-self: center;
    157   flex: none;
    158   --edge: var(--foam);
    159 }
    160 /* Vertical connector (TD): a hairline with a triangle arrowhead. */
    161 .prose .flow__diagram[data-dir='td'] > .flow-edge,
    162 .prose .flow-lane > .flow-edge {
    163   width: 1px;
    164   height: 2.3rem;
    165   background: var(--edge);
    166   margin: 0.05rem 0;
    167 }
    168 .prose .flow__diagram[data-dir='td'] > .flow-edge::after,
    169 .prose .flow-lane > .flow-edge::after {
    170   content: '';
    171   position: absolute;
    172   left: 50%; bottom: -1px;
    173   transform: translateX(-50%);
    174   border-left: 4px solid transparent;
    175   border-right: 4px solid transparent;
    176   border-top: 6px solid var(--edge);
    177 }
    178 /* Horizontal connector (LR). */
    179 .prose .flow__diagram[data-dir='lr'] > .flow-edge {
    180   height: 1px;
    181   width: clamp(1.8rem, 5vw, 3rem);
    182   background: var(--edge);
    183   margin: 0 0.05rem;
    184 }
    185 .prose .flow__diagram[data-dir='lr'] > .flow-edge::after {
    186   content: '';
    187   position: absolute;
    188   top: 50%; right: -1px;
    189   transform: translateY(-50%);
    190   border-top: 4px solid transparent;
    191   border-bottom: 4px solid transparent;
    192   border-left: 6px solid var(--edge);
    193 }
    194 /* The label a mermaid `-->|text|` edge carried — a knockout chip centred on
    195    the connector so the line reads through it. */
    196 .prose .flow-edge__label {
    197   position: absolute;
    198   left: 50%; top: 50%;
    199   transform: translate(-50%, -50%);
    200   background: var(--plate);
    201   border: 1px solid var(--rule);
    202   color: var(--foam);
    203   font-family: var(--font-term);
    204   font-size: 9.5px;
    205   letter-spacing: 0.04em;
    206   line-height: 1.1;
    207   padding: 0.1rem 0.4rem;
    208   white-space: nowrap;
    209   z-index: 3;
    210 }
    211 .prose .flow-edge.is-back { --edge: var(--love); background: none; }
    212 .prose .flow-edge.is-back.is-vert,
    213 .prose .flow__diagram[data-dir='td'] > .flow-edge.is-back { border-left: 1px dashed var(--love); width: 0; background: none; }
    214 .prose .flow-edge.is-dotted { background: none; border-top: 1px dashed var(--foam); }
    215 
    216 /* ---- Branch / merge ----------------------------------------------------- */
    217 /* A decision fans out into lanes; each lane is its own little TD sub-flow
    218    (labelled edge → node → …). */
    219 .prose .flow-branches {
    220   display: flex;
    221   gap: clamp(0.9rem, 4vw, 2.6rem);
    222   align-items: flex-start;
    223   justify-content: center;
    224 }
    225 .prose .flow-lane {
    226   display: flex;
    227   flex-direction: column;
    228   align-items: center;
    229 }
    230 /* A join bar collects several lanes back into one node: a hairline spanning
    231    the lanes with a single arrow dropping to the shared node below. */
    232 .prose .flow-join {
    233   position: relative;
    234   align-self: stretch;
    235   height: 1.6rem;
    236   margin-top: 0.1rem;
    237   /* Room for the drop line and arrowhead below; the diagram has no gap. */
    238   margin-bottom: 1.55rem;
    239   border-top: 1px solid var(--foam);
    240   border-left: 1px solid var(--foam);
    241   border-right: 1px solid var(--foam);
    242 }
    243 .prose .flow-join::after {
    244   content: '';
    245   position: absolute;
    246   left: 50%; bottom: -1.5rem;
    247   width: 1px; height: 1.5rem;
    248   background: var(--foam);
    249   transform: translateX(-50%);
    250 }
    251 /* Arrowhead where the gather-bracket drops into the shared node below. */
    252 .prose .flow-join::before {
    253   content: '';
    254   position: absolute;
    255   left: 50%; bottom: -1.55rem;
    256   transform: translateX(-50%);
    257   border-left: 4px solid transparent;
    258   border-right: 4px solid transparent;
    259   border-top: 6px solid var(--foam);
    260   z-index: 1;
    261 }
    262 
    263 /* ---- SVG-flow ----------------------------------------------------------- */
    264 /* One inline <svg class="flow-svg"> per complex graph, drawn on an orthogonal
    265    grid. Every colour comes from a token resolved in the `.plate` subtree, so
    266    the diagram flips with the theme like everything else. */
    267 .prose .flow-svg {
    268   display: block;
    269   width: 100%;
    270   height: auto;
    271   max-width: 100%;
    272   min-width: 0;
    273   font-family: var(--font-term);
    274   overflow: visible;
    275 }
    276 .prose .flow-svg text { fill: var(--text); }
    277 
    278 /* Node box + label. */
    279 .prose .flow-svg .fnode__box {
    280   fill: var(--surface);
    281   stroke: var(--rule-hi);
    282   stroke-width: 1;
    283 }
    284 .prose .flow-svg .fnode__label { fill: var(--text); font-size: 13px; }
    285 .prose .flow-svg .fnode__label .sub { fill: var(--subtle); font-size: 11px; }
    286 
    287 /* Node roles mirror the CSS-flow ones. */
    288 .prose .flow-svg .is-entry .fnode__box { stroke: var(--iris); stroke-width: 1.4; }
    289 .prose .flow-svg .is-goal .fnode__box { fill: color-mix(in srgb, var(--pine) 34%, var(--surface)); stroke: var(--foam); }
    290 .prose .flow-svg .is-note .fnode__box { fill: var(--overlay); stroke: var(--rule); stroke-dasharray: 4 3; }
    291 .prose .flow-svg .is-note .fnode__label { fill: var(--subtle); }
    292 .prose .flow-svg .is-danger .fnode__box { stroke: var(--love); }
    293 
    294 /* Decision diamond. */
    295 .prose .flow-svg .fdecision__poly { fill: var(--overlay); stroke: var(--gold); stroke-width: 1; }
    296 .prose .flow-svg .fdecision__label { fill: var(--text); font-size: 12px; }
    297 /* A text-heavy decision that won't fit a diamond: a gold-bordered rect node,
    298    matching the CSS-flow `.is-decision` box. */
    299 .prose .flow-svg .is-decision .fnode__box { fill: var(--overlay); stroke: var(--gold); }
    300 
    301 /* Edges. `context-stroke` on the arrowhead makes one shared marker take each
    302    edge's own colour, so a foam forward edge and a love back-edge point in
    303    their own ink from a single <marker> def. */
    304 .prose .flow-svg .fedge {
    305   fill: none;
    306   stroke: var(--foam);
    307   stroke-width: 1.5;
    308 }
    309 .prose .flow-svg .fedge.is-back { stroke: var(--love); stroke-dasharray: 5 3; }
    310 .prose .flow-svg .fedge.is-dotted { stroke: var(--foam); stroke-dasharray: 2 3; }
    311 .prose .flow-svg .fedge.is-thick { stroke: var(--iris); stroke-width: 2.4; }
    312 
    313 /* Edge label — a knockout chip like the CSS-flow one. */
    314 .prose .flow-svg .felabel__box { fill: var(--plate); stroke: var(--rule); stroke-width: 1; }
    315 .prose .flow-svg .felabel__text { fill: var(--foam); font-size: 11px; }
    316 
    317 /* The shared arrowhead marker lives once, hidden, in the sheet layout
    318    (see Base.astro). These fallbacks apply if a diagram ships its own <defs>. */
    319 .prose .flow-svg .flow-arrow { fill: context-stroke; }
    320 
    321 /* ---- Responsive --------------------------------------------------------- */
    322 @media (max-width: 620px) {
    323   /* An LR chain becomes a TD stack on a phone: the row wraps and each edge
    324      turns to point down. */
    325   .prose .flow__diagram[data-dir='lr'] { flex-direction: column; }
    326   .prose .flow__diagram[data-dir='lr'] > .flow-edge {
    327     width: 1px;
    328     height: 1.9rem;
    329     margin: 0.05rem 0;
    330   }
    331   .prose .flow__diagram[data-dir='lr'] > .flow-edge::after {
    332     top: auto; right: auto;
    333     left: 50%; bottom: -1px;
    334     transform: translateX(-50%);
    335     border-left: 4px solid transparent;
    336     border-right: 4px solid transparent;
    337     border-top: 6px solid var(--edge);
    338     border-bottom: 0;
    339   }
    340   .prose .flow-node { min-width: 7rem; font-size: 12px; }
    341 }
    342 
    343 @media (prefers-reduced-motion: no-preference) {
    344   /* Motion is opt-in across the site; the flow is static furniture and adds
    345      none of its own. */
    346 }