---
title: "S22 Compress · Second take · round 2"
description: "Contract, a board per state (idle, recording, paused, autostop, too-short, permission-denied, interrupted, loading, empty, error, offline), tokens and strings."
source: "design/hifi/S22/screen.md"
---

> Part of [Brand and design](/design/llms.txt). Every page: [llms.txt](/llms.txt).

# Hi-fi: S22 Compress · Second take · round 2

> Generated by `botgumi-design index` from `../../screens.json`. Edit that file, not this page.

Stage: **hifi** · Key: `compress/compress` · Data-binding map: [bindings.md](/design/hifi/s22/bindings/index.md)

Drawn in the gallery: [Compress](/design/gallery/index.html#g-compress). Each board is the committed HTML in `screens/`, drawn on the example data in `docs/api/examples/`.

## Contract

- **idle**: Mic button ink, CTA disabled. Recording never starts without a tap (D6). Round 2 shows the single previous advice on top — never the article.
- **recording**: Coral button = pause. Timer counts effective (unpaused) time. Persistent in-app recording indicator + iOS orange dot. CTA enabled at ≥ 20 s. Round 2 shows the single previous advice on top — never the article.
- **paused**: Paused time is not counted. Waveform freezes grey. Submit allowed if ≥ 20 s. Round 2 shows the single previous advice on top — never the article.
- **autostop**: Reached max duration; capture stopped automatically, confirm sheet. Haptic: warning. Round 2 shows the single previous advice on top — never the article.
- **too-short**: User tried to finish (or the level meter saw silence) under 20 s effective. Continue keeps the same file. Round 2 shows the single previous advice on top — never the article.
- **permission-denied**: Microphone denied. No attempt is created. Deep link to Settings; article and stage preserved. Round 2 shows the single previous advice on top — never the article.
- **interrupted**: Call / Siri / route change paused capture and persisted the partial file. Resume or re-record (D2). Round 2 shows the single previous advice on top — never the article.

Flows: F2 Daily quest.

Reads and calls:

- `GET /v1/sessions/{id} (stage = round2, round1_assessment.one_action, max_round2_ms)`
- `POST /v1/sessions/{id}/attempts {round, duration_ms, size_bytes, sha256, pause_count} → presigned PUT`
- `PUT upload.url`
- `POST /v1/attempts/{id}/submit`

Local state:

- `local:recorder.state (idle|recording|paused|stopped)`
- `local:recorder.effectiveMs`
- `local:recorder.levelDb (waveform)`
- `local:recorder.fileURL (persisted partial)`

## Boards

One row per state. A state without boards of its own says what shows it.

| State | Board | Example data |
|---|---|---|
| idle | [zh-Hans](/design/gallery/compress/compress--idle.html) · [en](/design/gallery/compress/compress--idle.en.html) | article-long.json ([zh-Hans](/design/examples/zh-Hans/article-long.json) · [en](/design/examples/en/article-long.json)), article-product.json ([zh-Hans](/design/examples/zh-Hans/article-product.json) · [en](/design/examples/en/article-product.json)) |
| recording | [zh-Hans](/design/gallery/compress/compress--recording.html) · [en](/design/gallery/compress/compress--recording.en.html) | article-long.json ([zh-Hans](/design/examples/zh-Hans/article-long.json) · [en](/design/examples/en/article-long.json)), article-product.json ([zh-Hans](/design/examples/zh-Hans/article-product.json) · [en](/design/examples/en/article-product.json)) |
| paused | [zh-Hans](/design/gallery/compress/compress--paused.html) · [en](/design/gallery/compress/compress--paused.en.html) | article-long.json ([zh-Hans](/design/examples/zh-Hans/article-long.json) · [en](/design/examples/en/article-long.json)), article-product.json ([zh-Hans](/design/examples/zh-Hans/article-product.json) · [en](/design/examples/en/article-product.json)) |
| autostop | [zh-Hans](/design/gallery/compress/compress--autostop.html) · [en](/design/gallery/compress/compress--autostop.en.html) | article-long.json ([zh-Hans](/design/examples/zh-Hans/article-long.json) · [en](/design/examples/en/article-long.json)), article-product.json ([zh-Hans](/design/examples/zh-Hans/article-product.json) · [en](/design/examples/en/article-product.json)) |
| too-short | [zh-Hans](/design/gallery/compress/compress--too-short.html) · [en](/design/gallery/compress/compress--too-short.en.html) | article-long.json ([zh-Hans](/design/examples/zh-Hans/article-long.json) · [en](/design/examples/en/article-long.json)), article-product.json ([zh-Hans](/design/examples/zh-Hans/article-product.json) · [en](/design/examples/en/article-product.json)) |
| permission-denied | [zh-Hans](/design/gallery/compress/compress--permission-denied.html) · [en](/design/gallery/compress/compress--permission-denied.en.html) | article-long.json ([zh-Hans](/design/examples/zh-Hans/article-long.json) · [en](/design/examples/en/article-long.json)), article-product.json ([zh-Hans](/design/examples/zh-Hans/article-product.json) · [en](/design/examples/en/article-product.json)) |
| interrupted | [zh-Hans](/design/gallery/compress/compress--interrupted.html) · [en](/design/gallery/compress/compress--interrupted.en.html) | article-long.json ([zh-Hans](/design/examples/zh-Hans/article-long.json) · [en](/design/examples/en/article-long.json)), article-product.json ([zh-Hans](/design/examples/zh-Hans/article-product.json) · [en](/design/examples/en/article-product.json)) |
| loading | [no board of its own](/design/hifi/s22/bindings/index.md#states): From [states.md](/design/states/index.md) (Record R1 / R2): — |  |
| empty | [no board of its own](/design/hifi/s22/bindings/index.md#states): From [states.md](/design/states/index.md) (Record R1 / R2): — |  |
| error | [no board of its own](/design/hifi/s22/bindings/index.md#states): From [states.md](/design/states/index.md) (Record R1 / R2): — · fatal: — |  |
| offline | [no board of its own](/design/hifi/s22/bindings/index.md#states): From [states.md](/design/states/index.md) (Record R1 / R2): records normally; banner via [offline--toast](/design/gallery/global/offline--toast.html) |  |

### The boards

Each state as drawn (393 × 852), one board per locale. Open a board on its own for its spec panel.

**idle**

[S22 idle · zh-Hans](/design/gallery/compress/compress--idle.html) [S22 idle · en](/design/gallery/compress/compress--idle.en.html)

**recording**

[S22 recording · zh-Hans](/design/gallery/compress/compress--recording.html) [S22 recording · en](/design/gallery/compress/compress--recording.en.html)

**paused**

[S22 paused · zh-Hans](/design/gallery/compress/compress--paused.html) [S22 paused · en](/design/gallery/compress/compress--paused.en.html)

**autostop**

[S22 autostop · zh-Hans](/design/gallery/compress/compress--autostop.html) [S22 autostop · en](/design/gallery/compress/compress--autostop.en.html)

**too-short**

[S22 too-short · zh-Hans](/design/gallery/compress/compress--too-short.html) [S22 too-short · en](/design/gallery/compress/compress--too-short.en.html)

**permission-denied**

[S22 permission-denied · zh-Hans](/design/gallery/compress/compress--permission-denied.html) [S22 permission-denied · en](/design/gallery/compress/compress--permission-denied.en.html)

**interrupted**

[S22 interrupted · zh-Hans](/design/gallery/compress/compress--interrupted.html) [S22 interrupted · en](/design/gallery/compress/compress--interrupted.en.html)

## Tokens used

By path in `../../system/tokens.source.json`.

| Token | Where |
|---|---|
| `color.accentPrimary` | `.btn--primary`, `.is-recording`, `.live`, `.r1` … |
| `color.accentPrimaryPressed` | `.btn--primary` |
| `color.accentPrimarySoft` | `.is-recording`, `.r2`, `.r3`, `.rec` … |
| `color.bgCanvas` | `.device`, `.dock`, `.navbar`, `.screen` |
| `color.bgInverse` | `.one-action`, `.rec-btn` |
| `color.bgInverseRaised` | `.icon-btn`, `.one-action` |
| `color.bgScrim` | `.scrim` |
| `color.bgSunken` | `.btn`, `.icon-btn`, `.paused`, `.rec` … |
| `color.bgSurface` | `.card`, `.is-paused`, `.rec`, `.rec-btn` … |
| `color.lineHairline` | `.card--flat`, `.progress-hair` |
| `color.lineStrong` | `.grabber`, `.r1`, `.r2`, `.r3` … |
| `color.recording` | `.rec-indicator` |
| `color.reward` | `.oa-head`, `.one-action` |
| `color.statusDanger` | `.rec-indicator` |
| `color.statusDangerSoft` | `.rec-indicator` |
| `color.textDisabled` | `.btn`, `.rec`, `.rec-btn` |
| `color.textOnAccent` | `.btn--primary` |
| `color.textOnInverse` | `.icon-btn`, `.one-action`, `.rec-btn` |
| `color.textOnInverseSecondary` | `.c-on-inverse-2` |
| `color.textPrimary` | `.device`, `.home-indicator`, `.icon-btn`, `.is-paused` … |
| `color.textSecondary` | `.btn--ghost`, `.c-secondary`, `.paused`, `.rec-indicator` … |
| `color.textTertiary` | `.c-tertiary`, `.frozen`, `.paused`, `.rec-indicator` … |
| `color.topicGreen` | `.tag--green` |
| `color.topicGreenSoft` | `.tag--green` |
| `radius.button` | `.btn` |
| `radius.card` | `.card` |
| `radius.lg` | `.one-action` |
| `radius.md` | `.card--md` |
| `radius.pill` | `.rec-indicator`, `.round-chip` |
| `radius.sm` | `.one-action` |
| `radius.xl` | `.sheet` |
| `space.gutter` | `.dock`, `.navbar`, `.pad`, `.sheet` |
| `space.s5` | `.card` |
| `space.s6` | `.screen` |
| `space.safeBottom` | `.dock`, `.dock-tall`, `.has-dock`, `.screen` … |
| `space.safeTop` | `.device`, `.screen` |
| `space.sizeCtaHeight` | `.btn`, `.dock-tall`, `.has-dock`, `.screen` |
| `space.sizeHitMin` | `.btn--ghost`, `.icon-btn` |
| `space.sizeNavbarHeight` | `.navbar` |
| `space.sizeRecordButton` | `.rec-btn` |
| `space.sizeRecordRing` | `.rec` |
| `space.sizeTabbarHeight` | `.screen` |
| `typography.body` | `.t-body` |
| `typography.footnote` | `.t-footnote` |
| `typography.headline` | `.t-headline` |
| `typography.subheadline` | `.t-subhead` |
| `typography.timer` | `.t-timer` |
| `typography.title1` | `.t-title1` |
| `typography.title2` | `.t-title2` |

## Strings

`app.name`, `common.back`, `common.continue`, `common.step_of.a11y`, `complete.ba.second`, `complete.xp.round2`, `feedback.confidence.low`, `feedback.evidence.pause.a11y`, `home.greeting.format`, `notif.daily.title`, `onboarding.progress.a11y`, `onboarding.welcome.illo.again`, `paywall.projection.score`, `profile.settings`, `profile.settings.a11y`, `record.advice.label`, `record.autostop.body`, `record.autostop.effective`, `record.autostop.submit`, `record.autostop.title`, `record.button.pause`, `record.button.resume`, `record.button.start`, `record.button.stopped`, `record.chip.round2`, `record.cta.caption`, `record.cta.round2`, `record.denied.back`, `record.denied.body`, `record.denied.cta`, `record.denied.step1`, `record.denied.step2`, `record.denied.step3`, `record.denied.title`, `record.hint.idle`, `record.hint.paused`, `record.hint.ready`, `record.indicator.paused`, `record.indicator.recording`, `record.interrupted.body`, `record.interrupted.title`, `record.nav.round1`, `record.nav.round2`, `record.rerecord`, `record.short.body`, `record.short.continue`, `record.short.title`, `record.sub.round2`, `record.title.round2`, `resume.cta`, `settings.nav`

## Notes for the app tracks

Motion, haptics, Dynamic Type and VoiceOver: [engagement.md](/design/engagement/index.md), [tokens.md](/design/tokens/index.md) §6–7 and
[ios-handoff.md](/design/ios-handoff/index.md). Open a board with `?theme=dark&dt=1.35&binds=1` to see dark mode, the largest
tested type size and every bound element.

Tracking-plan events: no tracking plan page exists yet; ADR-001 D12 names the events.

Tokens with no group in `system/tokens.source.json` yet (they stay in [tokens.css](/design/tokens.css)): `--dt`, `--elevation-1`, `--elevation-2`, `--elevation-3`, `--elevation-record`, `--font-family-numeric`, `--font-family-reading`, `--font-family-text`, `--font-weight-bold`, `--font-weight-heavy`, `--font-weight-regular`, `--font-weight-semibold`, `--motion-breath`, `--motion-duration-base`, `--motion-duration-fast`, `--motion-duration-instant`, `--motion-duration-slow`, `--motion-ease-emphasized`, `--motion-ease-spring`, `--motion-ease-standard`, `--type-tracking-tight`.
