--- version: alpha name: stickline-design description: "A dark charcoal-wood canvas (#1a1512) with warm paper ink (#f5efe6), the fourth neutral-dark palette built this batch but the only one paired with true safety-orange (#ff8a3d) and steel blue (#5fa8d3), colors pulled directly from real range-safety gear rather than a decorative pair. Big Shoulders Display carries every headline in uppercase, IBM Plex Sans carries prose and controls. The homepage runs four throws in sequence: an axe rotates and travels from the stickline to a target zone, sticking exactly on landing, before the next throw starts." --- ## Brand Positioning Stickline runs an axe-throwing venue, and it exists because most venues in this category sell bravado, a flannel-clad stock photo, "unleash your inner viking" copy, a house-invented "kill shot" bonus round that sounds extreme and means nothing. Stickline's bet is the opposite: show a real round, four throws, four real target zones, real point values, and name the actual safety rule the whole brand is named after. If a component doesn't correspond to a real zone, a real point value, or the stickline itself, it doesn't belong here. colors: accent: "#ff8a3d" accent-alt: "#5fa8d3" ink: "#f5efe6" ink-muted: "#b3a493" canvas: "#1a1512" ## Logo / Wordmark System The mark is the target in miniature, three concentric rings and a bullseye, with a single axe line crossing toward it from the lower left. It is not an axe alone, a flame, or a viking helmet. It is a reading of the same target the homepage's hero builds up. ```svg ``` - **Lockup**: mark, then a `0.55rem` gap, then "Stickline" in Big Shoulders Display 700, uppercase, `.02em` tracking. Mark always left of the wordmark. - **Minimum size**: mark not smaller than `18px`, below that the three rings merge into two. - **Clearspace**: empty margin equal to the mark's own width on all four sides. - **Don't**: don't recolor the bullseye to anything but `--accent`, it's the same orange as the hero's highest-value zone. Don't remove the axe line, without it the mark is just a target, not a throw in progress. Don't add a second axe line, one throw, one line. ## Color System ### Roles | Role | Token | Value | Used for | |---|---|---|---| | Canvas | `--bg` | `#1a1512` | Page background | | Surface | `--panel` | `#221b16` | Nav, zone cards, table, form card | | Surface raised | `--raised` | `#291f18` | Row hover, cta band, input focus fill | | Border | `--border` | `#33281f` | Card edges, table rules, dividers | | Border strong | `--border-strong` | `#453728` | Decorative-only edges, outer target ring | | Border UI | `--border-ui` | `#8a7660` | Every interactive boundary: secondary button, input, select, target ring outline | | Ink | `--ink` | `#f5efe6` | Headlines, body copy, table cells, axe head fill | | Ink muted | `--dim` | `#b3a493` | Labels, meta lines, helper text | | Safety orange | `--accent` | `#ff8a3d` | Primary button, bullseye zone, mark's center, highest point value | | Steel blue | `--accent-alt` | `#5fa8d3` | Ring three, "open today" status | Both accents are pulled from real range-safety and target colors, not chosen for decoration: safety orange is the color printed on real axe-throwing safety gear and marks this venue's own bullseye, steel blue is a genuine target-ring color. The two highest-scoring zones use the two accents, the two lower-scoring zones use neutral browns, so color intensity on the target rises with point value, the same logic the mark's own bullseye follows. ### Contrast (computed from the hex values above via WCAG relative luminance) | Pairing | Ratio | Passes | |---|---|---| | `--ink` on `--bg` (headlines, body copy) | 15.84:1 | AAA | | `--ink` on `--panel` (card copy, table cells) | 14.86:1 | AAA | | `--dim` on `--bg` (labels, helper text) | 7.46:1 | AAA | | `--dim` on `--raised` | 6.63:1 | AA | | `--accent` on `--bg` (links, point values) | 7.72:1 | AAA | | `--accent` on `--panel` | 7.24:1 | AAA | | `--accent` on `--raised` | 6.87:1 | AA | | `--accent-alt` on `--bg` (status text) | 6.92:1 | AA | | `--accent-alt` on `--panel` | 6.49:1 | AA | | dark label (`#1f0f02`) on `--accent` fill (primary button) | 7.94:1 | AAA | | `--border-ui` control edge on `--bg` (non-text, inputs) | 4.17:1 | AA (1.4.11) | | `--border-ui` control edge on `--panel` (non-text, secondary button) | 3.92:1 | AA (1.4.11) | `--border-strong` is kept for decorative-only uses, the outer target ring, a swatch outline, never a control boundary, `--border-ui` exists specifically so a real control never inherits that weaker value. typography: display: fontFamily: Big Shoulders Display fontWeight: 700 body: fontFamily: IBM Plex Sans fontWeight: 400 ## Type Scale | Token | Size | Weight | Family | Line-height | Letter-spacing | Used for | |---|---|---|---|---|---|---| | `--text-display` | `clamp(2.3rem, 5.5vw, 3.8rem)` | 700 | Big Shoulders Display | 1.05 | 0 | Homepage H1 | | `--text-page-h1` | `clamp(2rem, 4.5vw, 2.7rem)` | 700 | Big Shoulders Display | 1.08 | 0 | Second-page H1 | | `--text-h2` | `1.5rem` | 700 | Big Shoulders Display | 1.1 | 0 | Section headings | | `--text-points` | `1.9rem` | 700 | Big Shoulders Display | 1 | 0 | Zone point values | | `--text-body` | `1rem` | 400 | IBM Plex Sans | 1.6 | 0 | Paragraph copy | | `--text-small` | `0.88rem` | 400 | IBM Plex Sans | 1.55 | 0 | Table cells, footer, meta lines | | `--text-label` | `0.78rem` | 700 | IBM Plex Sans | 1 | 0.05em, uppercase | Form labels, table headers | Big Shoulders Display is a tall condensed face that reads as stamped and structural, set uppercase for headlines and point values, never for body copy where its condensed width would fight legibility at length. IBM Plex Sans carries every sentence and every control at 400 for prose and 700 for labels. ## Spacing Scale Base unit `8px`. Tokens in use: `--space-2: .5rem`, `--space-3: 1rem`, `--space-4: 1.5rem`, `--space-6: 2rem`, `--space-8: 3rem`, `--space-12: 4rem`. ## Shape `--radius: 3px` on cards, buttons, inputs, and the table wrap. `--radius-sm: 2px` on badges. Small and mostly square, reading as a target board and a safety line, not a soft or playful shape language. No shadows, no glows. ## Iconography No icon library. The only non-text graphics are the logo mark and the hero's own target-and-throw illustration (hand-built SVG). The thrown axe is a stylized mark, not a literal illustration, see Known Constraints. ## Motion Principles Scroll runs four throws in sequence. Each axe is drawn as a static group positioned at its exact landing coordinate and stuck angle, with an inner animated group carrying the actual throw: a combined translate and rotate that starts at the stickline's position with three full rotations of spin and eases down to zero offset and zero extra spin as the segment completes, so the axe arrives exactly at its drawn resting position and angle, never overshooting or needing a snap-back. One-shot sequence: nothing loops, and every zone is written out in the card grid regardless of scroll or script state. The scroll trigger measures the page's real available scroll room below the stage at load, minus a `16px` safety margin, and caps the run distance at that figure. A viewport tall enough to leave under `20px` of room, or a `prefers-reduced-motion` visitor, gets all four axes already stuck and every card already visible, with no scroll listener attached at all. ## Voice & Tone Blunt, safety-first, no bro-culture bravado. Stickline talks like a range safety officer who respects that you came here to have a good time, not like an ad selling extremity. In practice: - **Primary button**: "Book a lane", not "Unleash your inner viking" - **Zone description**: "Still on the board, still counts. Most first throws land here.", not "Not bad for a rookie!" - **Bullseye copy**: "Dead center. Buys you bragging rights for exactly one round.", not "You're a LEGEND!" - **Safety note**: named plainly under Known Constraints and on the lanes page, not softened into a suggestion. - **Status**: "Lanes open today, walk-ins fit between bookings." The tell that a sentence is off-brand: it performs extremity or aggression instead of stating the actual zone, value, or rule. ## Accessibility Baseline - **Focus ring**: `2px solid var(--accent)` at `2px` offset via `:focus-visible` on every link, button, input, and select, never removed. - **Reduced motion**: honored on every throw, as described under Motion Principles. No scroll listener is attached at all when reduce is set, or when there's no real scroll room to attach one to meaningfully. - **The target and throw graphic is `aria-hidden`.** It's a continuously changing illustration tied to scroll position. Nothing is communicated by it alone: every zone's name and point value is in the card grid below in plain markup at all times. - **Tap targets**: `44px` minimum height on every button, nav link, and form control. - **Structure**: one `

` per page, headings in order, `nav` / `main` / `footer` landmarks, `aria-current="page"` on the active nav link. ## Components ### Navigation Single line, `64px`, `--panel` with a `--border` bottom hairline, sticky. Left: the mark plus wordmark lockup. Right: a "Lanes" link and exactly one primary button. Below 480px the first nav link drops, the primary button stays. ### Buttons Two variants, `3px` radius, `44px` minimum height: - **Primary**: `--accent` fill, a near-black `#1f0f02` label, brightness lift on hover. Once per view, for the real action ("Book a lane"). - **Secondary**: transparent, `1px solid --border-ui`, `--ink` label, edge and label both going `--accent` on hover. ### The target and throw (signature) Documented in full under Motion Principles. Structurally: a static four-ring concentric target, four axe groups each with a static outer transform (landing position and stuck angle) and an animated inner transform (the throw itself). ### Zone card A flat panel: `--panel` background, `1px solid --border`, `3px` radius. Leads with the point value in large display type, then the zone name, then a real one-sentence description. Present in the DOM at all times, decorated by the reveal, never gated by it. ### Zone table (second page) `--raised` header row in `--text-label`, `--panel` body rows, one `--border` rule between rows, a `` naming the order. Below 700px the table restacks into one bordered block per zone. ### Notice A `--panel` block with a `3px` `--accent-alt` top rule, carrying the stickline safety rule. Square, matching the other systems built the same day, never a rounded card with a thick side or top accent stripe. ### Form Label above control in `--text-label`. Select and input share `--bg` fill, `1px solid --border-ui`, `3px` radius, `44px` height, `--raised` fill plus an accent border on focus. ### Footer Two-part row: an honest note that the venue is fictional, and a link list back to the other page and the gallery. No invented legal text. ## Do's and Don'ts ### Do - Let each axe's static landing transform and animated throw transform stay separate, so the drawn resting position is always exactly correct. - State a zone's point value in large type before its name. - Name the real stickline safety rule, since it's the brand's own name. - Measure real scroll room, minus a safety margin, before choosing a scroll-trigger distance. ### Don't - Don't use a stock photo of a flannel-clad thrower or a beard-and-axe cliche. - Don't write bravado copy. Name the actual zone and point value instead. - Don't use a cartoon axe mascot or motion-blur speed lines as decoration. - Don't replay the throw sequence on every scroll pass, it throws once, like a real round. - Don't round buttons into a pill, a target board reads geometric. - Don't invent a "kill shot" bonus zone that isn't one of the four real zones. ### Deliberate exception The lanes page's `.notice` element carries a `3px` `--accent-alt` top rule on `border-radius: 0`, the same square-plate treatment every other system built this batch reached for its own accent-bordered notice. The static-HTML pass of the mechanical detector still reports `border-accent-on-rounded` on that `border-top` declaration, because its regex engine matches the property text alone and can't see the resolved `border-radius: 0`, the same documented false positive every one of this batch's notices produces. The element is square, confirmed by reading the resolved CSS rule directly. ## Known Constraints - Two routes exist (home, lanes). There is no live availability calendar and no authenticated state. "Book a lane" produces a client-side confirmation only, this is a concept demo. - The thrown axe is a small stylized mark (a handle line and a wedge head), not a literal illustration. At the size it renders in the hero, roughly 20 to 30px including its rotation, a more detailed silhouette was tested and read as less clear, not more, so the simpler mark was kept deliberately rather than chasing photorealism the scale can't support. - The target holds exactly four zones with four fixed point values. This is a concept demo's simplified scoring, not any official league's actual rule set, and the copy never claims otherwise. - Responsive behavior is two breakpoints (900px, 700px, 480px) plus fluid type. There is no tablet-specific layout beyond the table's restack point. ## Process Built through the impeccable-audited anti-slop workflow: never-list written before any HTML, page structure derived from the signature interaction (the target and the throw) rather than a template, the scroll-trigger distance computed from real measured scroll room with a safety margin from the outset, and the mechanical detector run clean.